Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xaeae555ead9248aa100146a3caeda9a6c239c8bea2b165ce18ce5effae1cd5b0 | 0x60806040 | 19134564 | 181 days 23 hrs ago | 0x8f8c780dbc3ef64e86352a1198b58f98c8fa51a6 | IN | Create: AaveV3Borrow | 0 ETH | 0.003952099775 ETH |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
AaveV3Borrow
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Arbiscan on 2022-08-01 */ // 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 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 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 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"); } } } library TokenUtils { using SafeERC20 for IERC20; address public constant WETH_ADDR = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1; 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(); } } 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 ArbitrumAuthAddresses { address internal constant ADMIN_VAULT_ADDR = 0xd47D8D97cAd12A866900eEc6Cde1962529F25351; address internal constant FACTORY_ADDRESS = 0x5261abC3a94a6475D0A1171daE94A5f84fbaEcD2; address internal constant ADMIN_ADDR = 0x6AFEA85cFAB61e3a55Ad2e4537252Ec05796BEfa; } contract AuthHelper is ArbitrumAuthAddresses { } 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 ArbitrumActionsUtilAddresses { // TODO: set this address internal constant DFS_REG_CONTROLLER_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant SUB_STORAGE_ADDR = 0x24ab68395660b910BfBF1cc88BaA316BA06354eE; address internal constant REGISTRY_ADDR = 0xBF1CaC12DB60819Bfa71A328282ecbc1D40443aA; address internal constant DFS_LOGGER_ADDR = 0xE6f9A5C850dbcD12bc64f40d692F537250aDEC38; } contract ActionsUtilHelper is ArbitrumActionsUtilAddresses { } 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); } } contract ArbitrumAaveV3Addresses { address internal constant REWARDS_CONTROLLER_ADDRESS = 0x929EC64c34a17401F460460D4B9390518E5B473e; address internal constant DEFAULT_AAVE_MARKET = 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb; address internal constant TRANSIENT_STORAGE = 0x48cdE7c1f67fF11A62F6b4272166AB60EFB48C1F; } 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 AaveV3Helper is ArbitrumAaveV3Addresses { 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) { IAaveProtocolDataProvider dataProvider = getDataProvider(_market); (, uint256 borrowsStable, uint256 borrowsVariable, , , , , , ) = dataProvider.getUserReserveData(_tokenAddr, _debtOwner); if (_borrowType == STABLE_ID) { return borrowsStable; } else if (_borrowType == VARIABLE_ID) { return borrowsVariable; } } } contract AaveV3Borrow is ActionBase, AaveV3Helper { using TokenUtils for address; struct Params { uint256 amount; address to; uint8 rateMode; uint16 assetId; bool useDefaultMarket; bool useOnBehalf; address market; address onBehalf; } /// @inheritdoc ActionBase function executeAction( bytes memory _callData, bytes32[] memory _subData, uint8[] memory _paramMapping, bytes32[] memory _returnValues ) public payable virtual override returns (bytes32) { Params memory params = parseInputs(_callData); params.amount = _parseParamUint(params.amount, _paramMapping[0], _subData, _returnValues); params.to = _parseParamAddr(params.to, _paramMapping[1], _subData, _returnValues); params.rateMode = uint8(_parseParamUint(uint8(params.rateMode), _paramMapping[2], _subData, _returnValues)); params.assetId = uint16(_parseParamUint(uint16(params.assetId), _paramMapping[3], _subData, _returnValues)); params.useDefaultMarket = _parseParamUint(params.useDefaultMarket ? 1 : 0, _paramMapping[4], _subData, _returnValues) == 1; params.useOnBehalf = _parseParamUint(params.useOnBehalf ? 1 : 0, _paramMapping[5], _subData, _returnValues) == 1; params.market = _parseParamAddr(params.market, _paramMapping[6], _subData, _returnValues); params.onBehalf = _parseParamAddr( params.onBehalf, _paramMapping[7], _subData, _returnValues ); if (params.useDefaultMarket) { params.market = DEFAULT_AAVE_MARKET; } if (!params.useOnBehalf) { params.onBehalf = address(0); } (uint256 borrowAmount, bytes memory logData) = _borrow( params.market, params.assetId, params.amount, params.rateMode, params.to, params.onBehalf ); emit ActionEvent("AaveV3Borrow", logData); return bytes32(borrowAmount); } /// @inheritdoc ActionBase /// @dev Only used on L2 currently, must parse inputs here if implemented later on function executeActionDirect(bytes memory _callData) public payable override {} function executeActionDirectL2() public payable { Params memory params = decodeInputs(msg.data[4:]); (, bytes memory logData) = _borrow( params.market, params.assetId, params.amount, params.rateMode, params.to, params.onBehalf ); logger.logActionDirectEvent("AaveV3Borrow", logData); } /// @inheritdoc ActionBase function actionType() public pure virtual override returns (uint8) { return uint8(ActionType.STANDARD_ACTION); } //////////////////////////// ACTION LOGIC //////////////////////////// /// @notice User borrows tokens from the Aave protocol /// @param _market Address provider for specific market /// @param _assetId The id of the token to be borrowed /// @param _amount Amount of tokens to be borrowed /// @param _rateMode Type of borrow debt [Stable: 1, Variable: 2] /// @param _to The address we are sending the borrowed tokens to /// @param _onBehalf On whose behalf we borrow the tokens, defaults to proxy function _borrow( address _market, uint16 _assetId, uint256 _amount, uint256 _rateMode, address _to, address _onBehalf ) internal returns (uint256, bytes memory) { IPoolV3 lendingPool = getLendingPool(_market); address tokenAddr = lendingPool.getReserveAddressById(_assetId); // defaults to onBehalf of proxy if (_onBehalf == address(0)) { _onBehalf = address(this); } lendingPool.borrow(tokenAddr, _amount, _rateMode, AAVE_REFERRAL_CODE, _onBehalf); _amount = tokenAddr.withdrawTokens(_to, _amount); bytes memory logData = abi.encode(_market, tokenAddr, _amount, _rateMode, _to, _onBehalf); 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, bytes32(params.amount)); encodedInput = bytes.concat(encodedInput, bytes20(params.to)); encodedInput = bytes.concat(encodedInput, bytes1(params.rateMode)); encodedInput = bytes.concat(encodedInput, bytes2(params.assetId)); encodedInput = bytes.concat(encodedInput, boolToBytes(params.useDefaultMarket)); encodedInput = bytes.concat(encodedInput, boolToBytes(params.useOnBehalf)); if (!params.useDefaultMarket) { encodedInput = bytes.concat(encodedInput, bytes20(params.market)); } if (params.useOnBehalf) { encodedInput = bytes.concat(encodedInput, bytes20(params.onBehalf)); } } function decodeInputs(bytes calldata encodedInput) public pure returns (Params memory params) { params.amount = uint256(bytes32(encodedInput[0:32])); params.to = address(bytes20(encodedInput[32:52])); params.rateMode = uint8(bytes1(encodedInput[52:53])); params.assetId = uint16(bytes2(encodedInput[53:55])); params.useDefaultMarket = bytesToBool(bytes1(encodedInput[55:56])); params.useOnBehalf = bytesToBool(bytes1(encodedInput[56:57])); uint256 mark = 57; if (params.useDefaultMarket) { params.market = DEFAULT_AAVE_MARKET; } else { params.market = address(bytes20(encodedInput[mark:mark + 20])); mark += 20; } if (params.useOnBehalf) { params.onBehalf = address(bytes20(encodedInput[mark:mark + 20])); } else { params.onBehalf = address(0); } } }
[{"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":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint8","name":"rateMode","type":"uint8"},{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"bool","name":"useOnBehalf","type":"bool"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"onBehalf","type":"address"}],"internalType":"struct AaveV3Borrow.Params","name":"params","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint8","name":"rateMode","type":"uint8"},{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"bool","name":"useOnBehalf","type":"bool"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"onBehalf","type":"address"}],"internalType":"struct AaveV3Borrow.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":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint8","name":"rateMode","type":"uint8"},{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"bool","name":"useOnBehalf","type":"bool"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"onBehalf","type":"address"}],"internalType":"struct AaveV3Borrow.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
608060405234801561001057600080fd5b50612202806100206000396000f3fe60806040526004361061015f5760003560e01c80638bcb6216116100c0578063c579d49011610074578063d4f922dc11610059578063d4f922dc14610368578063e197b16c1461037d578063f24ccbfe146103aa57600080fd5b8063c579d49014610333578063d3c2e7ed1461035357600080fd5b80638df50f74116100a55780638df50f74146102eb5780639093410d146102fe5780639864dcdd1461031e57600080fd5b80638bcb6216146102ae5780638cedca71146102c357600080fd5b80632fa13cb81161011757806341c0e1b5116100fc57806341c0e1b51461021f5780637b103999146102345780638b8359791461028157600080fd5b80632fa13cb8146101f9578063389f87ff1461020e57600080fd5b8063247492f811610148578063247492f8146101b85780632895f3aa146101cc5780632ba38bcb146101d657600080fd5b806305a363de146101645780630f2eee4214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101a6608081565b60405160ff9091168152602001610188565b3480156101c457600080fd5b5060016101a6565b6101d46103d2565b005b3480156101e257600080fd5b506101eb600181565b604051908152602001610188565b34801561020557600080fd5b506101a6600081565b6101d461021c3660046118c7565b50565b34801561022b57600080fd5b506101d461049b565b34801561024057600080fd5b5061025c73bf1cac12db60819bfa71a328282ecbc1d40443aa81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b34801561028d57600080fd5b506102a161029c3660046118fc565b610585565b604051610188919061196e565b3480156102ba57600080fd5b506101a6600181565b3480156102cf57600080fd5b5061025c73d47d8d97cad12a866900eec6cde1962529f2535181565b6101eb6102f9366004611ac3565b61074c565b34801561030a57600080fd5b506102a16103193660046118c7565b6109df565b34801561032a57600080fd5b506101a6607f81565b34801561033f57600080fd5b506101d461034e366004611bf9565b610a38565b34801561035f57600080fd5b506101a660ff81565b34801561037457600080fd5b506101eb600281565b34801561038957600080fd5b5061039d610398366004611c6e565b610bc0565b6040516101889190611d85565b3480156103b657600080fd5b5061025c73e6f9a5c850dbcd12bc64f40d692f537250adec3881565b60006103e461029c3660048185611d98565b905060006104118260c0015183606001518460000151856040015160ff1686602001518760e00151610d6e565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073e6f9a5c850dbcd12bc64f40d692f537250adec38915063f4b24b5590610465908490600401611dc2565b600060405180830381600087803b15801561047f57600080fd5b505af1158015610493573d6000803e3d6000fd5b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190611e14565b73ffffffffffffffffffffffffffffffffffffffff1614610582576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526105d4602060008486611d98565b6105dd91611e31565b81526105ed603460208486611d98565b6105f691611e6d565b60601c602082015261060c603560348486611d98565b61061591611eb3565b60f81c604082015261062b603760358486611d98565b61063491611ef9565b60f01c606082015261067d61064d603860378587611d98565b61065691611eb3565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b1515608082015261069561064d603960388587611d98565b151560a08201526080810151603990156106c85773a97684ead0e402dc232d5a977953df7ecbab3cdb60c0830152610702565b8381846106d6826014611f6e565b926106e393929190611d98565b6106ec91611e6d565b60601c60c08301526106ff601482611f6e565b90505b8160a001511561073d5783818461071a826014611f6e565b9261072793929190611d98565b61073091611e6d565b60601c60e0830152610745565b600060e08301525b5092915050565b600080610758866109df565b905061078481600001518560008151811061077557610775611f86565b60200260200101518786610f63565b8152602081015184516107b49190869060019081106107a5576107a5611f86565b60200260200101518786610fdf565b73ffffffffffffffffffffffffffffffffffffffff166020820152604081015184516107f19160ff16908690600290811061077557610775611f86565b60ff1660408201526060810151845161081c9161ffff16908690600390811061077557610775611f86565b61ffff16606082015260808101516108529061083957600061083c565b60015b60ff168560048151811061077557610775611f86565b600114608082015260a08101516108879061086e576000610871565b60015b60ff168560058151811061077557610775611f86565b60011460a082015260c081015184516108ae9190869060069081106107a5576107a5611f86565b73ffffffffffffffffffffffffffffffffffffffff1660c082015260e081015184516108e89190869060079081106107a5576107a5611f86565b73ffffffffffffffffffffffffffffffffffffffff1660e08201526080810151156109285773a97684ead0e402dc232d5a977953df7ecbab3cdb60c08201525b8060a0015161093957600060e08201525b6000806109658360c0015184606001518560000151866040015160ff1687602001518860e00151610d6e565b6040517f416176655633426f72726f77000000000000000000000000000000000000000081529193509150600c0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce3826040516109ca9190611d85565b60405180910390a2509150505b949350505050565b604080516101008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082015282519091610a329184018101908401611fcb565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad29190611e14565b73ffffffffffffffffffffffffffffffffffffffff1614610b1f576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610b9a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610b94573d6000803e3d6000fd5b50505050565b610bbb73ffffffffffffffffffffffffffffffffffffffff841683836110bc565b505050565b604080517f2895f3aa00000000000000000000000000000000000000000000000000000000602082015281516004818303018152602482019092528251610c0c91839190604401612060565b604051602081830303815290604052905080826020015160601b604051602001610c37929190612082565b604051602081830303815290604052905080826040015160f81b604051602001610c629291906120c9565b604051602081830303815290604052905080826060015160f01b604051602001610c8d929190612110565b604051602081830303815290604052905080610cac8360800151611149565b604051602001610cbd9291906120c9565b604051602081830303815290604052905080610cdc8360a00151611149565b604051602001610ced9291906120c9565b60405160208183030381529060405290508160800151610d3357808260c0015160601b604051602001610d21929190612082565b60405160208183030381529060405290505b8160a0015115610d6957808260e0015160601b604051602001610d57929190612082565b60405160208183030381529060405290505b919050565b600060606000610d7d8961117e565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8a16600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610df1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e159190611e14565b905073ffffffffffffffffffffffffffffffffffffffff8516610e36573094505b604080517fa415bcad00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018b9052604482018a9052606482019290925286821660848201529083169063a415bcad9060a401600060405180830381600087803b158015610ebf57600080fd5b505af1158015610ed3573d6000803e3d6000fd5b50610ef99250505073ffffffffffffffffffffffffffffffffffffffff8216878a6111ef565b6040805173ffffffffffffffffffffffffffffffffffffffff9c8d166020820152928c1683820152606083018290526080830198909852958a1660a08201529390981660c0808501919091528551808503909101815260e090930190945250909590945092505050565b600060ff841615610fd657610f778461139f565b15610fab5781610f86856113be565b60ff1681518110610f9957610f99611f86565b602002602001015160001c9450610fd6565b82610fb58561140a565b60ff1681518110610fc857610fc8611f86565b602002602001015160001c94505b50929392505050565b600060ff841615610fd657610ff38461139f565b156110275781611002856113be565b60ff168151811061101557611015611f86565b602002602001015160601c9450610fd6565b8360ff1660fe141561103a5750306109d7565b8360ff1660ff1415610fab573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611091573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b59190611e14565b90506109d7565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610bbb908490611455565b600081611157576000610a32565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a329190611e14565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611226576112238430611561565b91505b73ffffffffffffffffffffffffffffffffffffffff831615801590611261575073ffffffffffffffffffffffffffffffffffffffff83163014155b801561126c57508115155b156107455773ffffffffffffffffffffffffffffffffffffffff841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146112c8576112c373ffffffffffffffffffffffffffffffffffffffff851684846110bc565b610745565b60008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114611322576040519150601f19603f3d011682016040523d82523d6000602084013e611327565b606091505b5050905080611397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4574682073656e64206661696c0000000000000000000000000000000000000060448201526064015b60405180910390fd5b505092915050565b6000600160ff831610801590610a325750607f60ff8316111592915050565b60006113c98261139f565b6113ff576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a32600183612157565b6000608060ff8316101561144a576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a32608083612157565b60006114b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661164a9092919063ffffffff16565b805190915015610bbb57808060200190518101906114d5919061217a565b610bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161138e565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156115b3575073ffffffffffffffffffffffffffffffffffffffff811631610a32565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa15801561161f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116439190612197565b9392505050565b60606109d78484600085606061165f85611758565b611695576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516116be91906121b0565b60006040518083038185875af1925050503d80600081146116fb576040519150601f19603f3d011682016040523d82523d6000602084013e611700565b606091505b509150915081156117145791506109d79050565b8051156117245780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138e9190611d85565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906109d7575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156117e4576117e4611791565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561183157611831611791565b604052919050565b600082601f83011261184a57600080fd5b813567ffffffffffffffff81111561186457611864611791565b61189560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016117ea565b8181528460208386010111156118aa57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156118d957600080fd5b813567ffffffffffffffff8111156118f057600080fd5b6109d784828501611839565b6000806020838503121561190f57600080fd5b823567ffffffffffffffff8082111561192757600080fd5b818501915085601f83011261193b57600080fd5b81358181111561194a57600080fd5b86602082850101111561195c57600080fd5b60209290920196919550909350505050565b6000610100820190508251825273ffffffffffffffffffffffffffffffffffffffff602084015116602083015260ff604084015116604083015261ffff606084015116606083015260808301511515608083015260a08301516119d560a084018215159052565b5060c08301516119fd60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161074560e084018273ffffffffffffffffffffffffffffffffffffffff169052565b600067ffffffffffffffff821115611a3f57611a3f611791565b5060051b60200190565b600082601f830112611a5a57600080fd5b81356020611a6f611a6a83611a25565b6117ea565b82815260059290921b84018101918181019086841115611a8e57600080fd5b8286015b84811015611aa95780358352918301918301611a92565b509695505050505050565b60ff8116811461021c57600080fd5b60008060008060808587031215611ad957600080fd5b843567ffffffffffffffff80821115611af157600080fd5b611afd88838901611839565b9550602091508187013581811115611b1457600080fd5b611b2089828a01611a49565b955050604087013581811115611b3557600080fd5b8701601f81018913611b4657600080fd5b8035611b54611a6a82611a25565b81815260059190911b8201840190848101908b831115611b7357600080fd5b928501925b82841015611b9a578335611b8b81611ab4565b82529285019290850190611b78565b96505050506060870135915080821115611bb357600080fd5b50611bc087828801611a49565b91505092959194509250565b73ffffffffffffffffffffffffffffffffffffffff8116811461021c57600080fd5b8035610d6981611bcc565b600080600060608486031215611c0e57600080fd5b8335611c1981611bcc565b92506020840135611c2981611bcc565b929592945050506040919091013590565b61ffff8116811461021c57600080fd5b8035610d6981611c3a565b801515811461021c57600080fd5b8035610d6981611c55565b60006101008284031215611c8157600080fd5b611c896117c0565b823581526020830135611c9b81611bcc565b60208201526040830135611cae81611ab4565b6040820152611cbf60608401611c4a565b6060820152611cd060808401611c63565b6080820152611ce160a08401611c63565b60a0820152611cf260c08401611bee565b60c0820152611d0360e08401611bee565b60e08201529392505050565b60005b83811015611d2a578181015183820152602001611d12565b83811115610b945750506000910152565b60008151808452611d53816020860160208601611d0f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006116436020830184611d3b565b60008085851115611da857600080fd5b83861115611db557600080fd5b5050820193919092039150565b60408152600c60408201527f416176655633426f72726f77000000000000000000000000000000000000000060608201526080602082015260006116436080830184611d3b565b8051610d6981611bcc565b600060208284031215611e2657600080fd5b815161164381611bcc565b80356020831015610a32577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156113975760149490940360031b84901b1690921692915050565b7fff0000000000000000000000000000000000000000000000000000000000000081358181169160018510156113975760019490940360031b84901b1690921692915050565b7fffff00000000000000000000000000000000000000000000000000000000000081358181169160028510156113975760029490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611f8157611f81611f3f565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051610d6981611c3a565b8051610d6981611c55565b60006101008284031215611fde57600080fd5b611fe66117c0565b825181526020830151611ff881611bcc565b6020820152604083015161200b81611ab4565b604082015261201c60608401611fb5565b606082015261202d60808401611fc0565b608082015261203e60a08401611fc0565b60a082015261204f60c08401611e09565b60c0820152611d0360e08401611e09565b60008351612072818460208801611d0f565b9190910191825250602001919050565b60008351612094818460208801611d0f565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b600083516120db818460208801611d0f565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351612122818460208801611d0f565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b600060ff821660ff84168082101561217157612171611f3f565b90039392505050565b60006020828403121561218c57600080fd5b815161164381611c55565b6000602082840312156121a957600080fd5b5051919050565b600082516121c2818460208701611d0f565b919091019291505056fea2646970667358221220f9aae889a30a68f39ade07c9f21706096049cf882c33c51f42b37d3843ba64a264736f6c634300080a0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.