My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xcfa3b531b78408dcbb51cd198b0dd6e87db79e4e183e42e773d95e43677340ca | 0x60806040 | 19127656 | 595 days 16 hrs ago | 0x8f8c780dbc3ef64e86352a1198b58f98c8fa51a6 | IN | Create: AaveV3Withdraw | 0 ETH | 0.002754758514 ETH |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
AaveV3Withdraw
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Arbiscan.io 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 AaveV3Withdraw is ActionBase, AaveV3Helper { using TokenUtils for address; struct Params { uint16 assetId; bool useDefaultMarket; uint256 amount; address to; address market; } /// @inheritdoc ActionBase function executeAction( bytes calldata callData, bytes32[] memory _subData, uint8[] memory _paramMapping, bytes32[] memory _returnValues ) public payable virtual override returns (bytes32) { Params memory params = parseInputs(callData); params.assetId = uint16(_parseParamUint(uint16(params.assetId), _paramMapping[0], _subData, _returnValues)); params.useDefaultMarket = _parseParamUint(params.useDefaultMarket ? 1 : 0, _paramMapping[1], _subData, _returnValues) == 1; params.amount = _parseParamUint(params.amount, _paramMapping[2], _subData, _returnValues); params.to = _parseParamAddr(params.to, _paramMapping[3], _subData, _returnValues); params.market = _parseParamAddr(params.market, _paramMapping[4], _subData, _returnValues); if (params.useDefaultMarket) { params.market = DEFAULT_AAVE_MARKET; } (uint256 withdrawnAmount, bytes memory logData) = _withdraw( params.market, params.assetId, params.amount, params.to ); emit ActionEvent("AaveV3Withdraw", logData); return bytes32(withdrawnAmount); } /// @inheritdoc ActionBase /// @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) = _withdraw( params.market, params.assetId, params.amount, params.to ); logger.logActionDirectEvent("AaveV3Withdraw", logData); } /// @inheritdoc ActionBase function actionType() public pure virtual override returns (uint8) { return uint8(ActionType.STANDARD_ACTION); } //////////////////////////// ACTION LOGIC //////////////////////////// /// @notice User withdraws tokens from the Aave protocol /// @param _market Address provider for specific market /// @param _assetId The id of the token to be deposited /// @param _amount Amount of tokens to be withdrawn -> send type(uint).max for whole amount /// @param _to Where the withdrawn tokens will be sent function _withdraw( address _market, uint16 _assetId, uint256 _amount, address _to ) internal returns (uint256, bytes memory) { IPoolV3 lendingPool = getLendingPool(_market); address tokenAddr = lendingPool.getReserveAddressById(_assetId); uint256 tokenBefore; // only need to remember this is _amount is max, no need to waste gas otherwise if (_amount == type(uint256).max) { tokenBefore = tokenAddr.getBalance(_to); } // withdraw underlying tokens from aave and send _to address lendingPool.withdraw(tokenAddr, _amount, _to); // if the input amount is max calc. what was the exact _amount if (_amount == type(uint256).max) { _amount = tokenAddr.getBalance(_to) - tokenBefore; } bytes memory logData = abi.encode(_market, tokenAddr, _amount, _to); return (_amount, logData); } function parseInputs(bytes memory _callData) public pure returns (Params memory params) { params = abi.decode(_callData, (Params)); } function encodeInputs(Params memory params) public pure returns (bytes memory encodedInput) { encodedInput = bytes.concat(this.executeActionDirectL2.selector); encodedInput = bytes.concat(encodedInput, bytes2(params.assetId)); encodedInput = bytes.concat(encodedInput, boolToBytes(params.useDefaultMarket)); encodedInput = bytes.concat(encodedInput, bytes32(params.amount)); encodedInput = bytes.concat(encodedInput, bytes20(params.to)); if (!params.useDefaultMarket) { encodedInput = bytes.concat(encodedInput, bytes20(params.market)); } } function decodeInputs(bytes calldata encodedInput) public view returns (Params memory params) { params.assetId = uint16(bytes2(encodedInput[0:2])); params.useDefaultMarket = bytesToBool(bytes1(encodedInput[2:3])); params.amount = uint256(bytes32(encodedInput[3:35])); params.to = address(bytes20(encodedInput[35:55])); if (params.useDefaultMarket) { params.market = DEFAULT_AAVE_MARKET; } else { params.market = address(bytes20(encodedInput[55:75])); } } }
[{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[],"name":"ReturnIndexValueError","type":"error"},{"inputs":[],"name":"SenderNotAdmin","type":"error"},{"inputs":[],"name":"SenderNotOwner","type":"error"},{"inputs":[],"name":"SubIndexValueError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"logName","type":"string"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ActionEvent","type":"event"},{"inputs":[],"name":"AAVE_REFERRAL_CODE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_PARAM_MAPPING","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VARIABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"adminVault","outputs":[{"internalType":"contract AdminVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedInput","type":"bytes"}],"name":"decodeInputs","outputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"name":"encodeInputs","outputs":[{"internalType":"bytes","name":"encodedInput","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32[]","name":"_subData","type":"bytes32[]"},{"internalType":"uint8[]","name":"_paramMapping","type":"uint8[]"},{"internalType":"bytes32[]","name":"_returnValues","type":"bytes32[]"}],"name":"executeAction","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_callData","type":"bytes"}],"name":"executeActionDirect","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"executeActionDirectL2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"logger","outputs":[{"internalType":"contract DefisaverLogger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_callData","type":"bytes"}],"name":"parseInputs","outputs":[{"components":[{"internalType":"uint16","name":"assetId","type":"uint16"},{"internalType":"bool","name":"useDefaultMarket","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"market","type":"address"}],"internalType":"struct AaveV3Withdraw.Params","name":"params","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract DFSRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50611de9806100206000396000f3fe60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d7578063d4f922dc146103ec578063f24ccbfe1461040157600080fd5b80639864dcdd146103a2578063c579d490146103b757600080fd5b80638cedca71116100a55780638cedca71146103475780638df50f741461036f5780639093410d1461038257600080fd5b80638b835979146102ae5780638bcb62161461033257600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024c5780637b1039991461026157600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac3660046115aa565b610429565b6040516101889190611691565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610562565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b6102016102493660046116ab565b50565b34801561025857600080fd5b5061020161061e565b34801561026d57600080fd5b5061028973bf1cac12db60819bfa71a328282ecbc1d40443aa81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102ba57600080fd5b506102ce6102c93660046117a7565b610708565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561033e57600080fd5b506101d3600181565b34801561035357600080fd5b5061028973d47d8d97cad12a866900eec6cde1962529f2535181565b61021861037d366004611878565b610822565b34801561038e57600080fd5b506102ce61039d3660046116ab565b610a33565b3480156103ae57600080fd5b506101d3607f81565b3480156103c357600080fd5b506102016103d236600461198e565b610a70565b3480156103e357600080fd5b506101d360ff81565b3480156103f857600080fd5b50610218600281565b34801561040d57600080fd5b5061028973e6f9a5c850dbcd12bc64f40d692f537250adec3881565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047891839160f01b906044016119cf565b6040516020818303038152906040529050806104978360200151610bf8565b6040516020016104a8929190611a16565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ec91839190602001611a5d565b604051602081830303815290604052905080826060015160601b604051602001610517929190611a7f565b6040516020818303038152906040529050816020015161055d5780826080015160601b60405160200161054b929190611a7f565b60405160208183030381529060405290505b919050565b60006105746102c93660048185611ac6565b905060006105948260800151836000015184604001518560600151610c2d565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073e6f9a5c850dbcd12bc64f40d692f537250adec38915063f4b24b55906105e8908490600401611af0565b600060405180830381600087803b15801561060257600080fd5b505af1158015610616573d6000803e3d6000fd5b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b89190611b37565b73ffffffffffffffffffffffffffffffffffffffff1614610705576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610741600260008486611ac6565b61074a91611b54565b60f01c8152610790610760600360028587611ac6565b61076991611b9c565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b151560208201526107a5602360038486611ac6565b6107ae91611be2565b60408201526107c1603760238486611ac6565b6107ca91611c1e565b606090811c908201526020810151156107fc5773a97684ead0e402dc232d5a977953df7ecbab3cdb608082015261081c565b61080a604b60378486611ac6565b61081391611c1e565b60601c60808201525b92915050565b60008061086487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a3392505050565b9050610894816000015161ffff168560008151811061088557610885611c64565b60200260200101518786610e73565b61ffff16815260208101516108c7906108ae5760006108b1565b60015b60ff168560018151811061088557610885611c64565b6001146020820152604081015184516108ee91908690600290811061088557610885611c64565b81604001818152505061092181606001518560038151811061091257610912611c64565b60200260200101518786610ef1565b73ffffffffffffffffffffffffffffffffffffffff1660608201526080810151845161095b91908690600490811061091257610912611c64565b73ffffffffffffffffffffffffffffffffffffffff16608082015260208101511561099b5773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201525b6000806109ba8360800151846000015185604001518660600151610c2d565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610a1f9190611691565b60405180910390a250979650505050505050565b6040805160a081018252600080825260208083018290529282018190526060820181905260808201528251909161081c9184018101908401611c93565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190611b37565b73ffffffffffffffffffffffffffffffffffffffff1614610b57576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610bd25760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610bcc573d6000803e3d6000fd5b50505050565b610bf373ffffffffffffffffffffffffffffffffffffffff84168383610fce565b505050565b600081610c0657600061081c565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610c3c8761105b565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd49190611b37565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610d2357610d2073ffffffffffffffffffffffffffffffffffffffff8316876110cc565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190611cf8565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610e1b5780610e0e73ffffffffffffffffffffffffffffffffffffffff8416886110cc565b610e189190611d40565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610ee657610e87846111b5565b15610ebb5781610e96856111d4565b60ff1681518110610ea957610ea9611c64565b602002602001015160001c9450610ee6565b82610ec585611220565b60ff1681518110610ed857610ed8611c64565b602002602001015160001c94505b50835b949350505050565b600060ff841615610ee657610f05846111b5565b15610f395781610f14856111d4565b60ff1681518110610f2757610f27611c64565b602002602001015160601c9450610ee6565b8360ff1660fe1415610f4c575030610ee9565b8360ff1660ff1415610ebb573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc79190611b37565b9050610ee9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610bf390849061126b565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611b37565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561111e575073ffffffffffffffffffffffffffffffffffffffff81163161081c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae9190611cf8565b905061081c565b6000600160ff83161080159061081c5750607f60ff8316111592915050565b60006111df826111b5565b611215576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61081c600183611d57565b6000608060ff83161015611260576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61081c608083611d57565b60006112cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661137c9092919063ffffffff16565b805190915015610bf357808060200190518101906112eb9190611d7a565b610bf3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610ee9848460008560606113918561148a565b6113c7576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516113f09190611d97565b60006040518083038185875af1925050503d806000811461142d576040519150601f19603f3d011682016040523d82523d6000602084013e611432565b606091505b50915091508115611446579150610ee99050565b8051156114565780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113739190611691565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610ee9575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611515576115156114c3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611562576115626114c3565b604052919050565b61ffff8116811461024957600080fd5b801515811461024957600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461024957600080fd5b600060a082840312156115bc57600080fd5b6115c46114f2565b82356115cf8161156a565b815260208301356115df8161157a565b60208201526040838101359082015260608301356115fc81611588565b6060820152608083013561160f81611588565b60808201529392505050565b60005b8381101561163657818101518382015260200161161e565b83811115610bcc5750506000910152565b6000815180845261165f81602086016020860161161b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006116a46020830184611647565b9392505050565b600060208083850312156116be57600080fd5b823567ffffffffffffffff808211156116d657600080fd5b818501915085601f8301126116ea57600080fd5b8135818111156116fc576116fc6114c3565b61172c847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161151b565b9150808252868482850101111561174257600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261177057600080fd5b50813567ffffffffffffffff81111561178857600080fd5b6020830191508360208285010111156117a057600080fd5b9250929050565b600080602083850312156117ba57600080fd5b823567ffffffffffffffff8111156117d157600080fd5b6117dd8582860161175e565b90969095509350505050565b600067ffffffffffffffff821115611803576118036114c3565b5060051b60200190565b600082601f83011261181e57600080fd5b8135602061183361182e836117e9565b61151b565b82815260059290921b8401810191818101908684111561185257600080fd5b8286015b8481101561186d5780358352918301918301611856565b509695505050505050565b60008060008060006080868803121561189057600080fd5b853567ffffffffffffffff808211156118a857600080fd5b6118b489838a0161175e565b90975095506020915087820135818111156118ce57600080fd5b6118da8a828b0161180d565b9550506040880135818111156118ef57600080fd5b8801601f81018a1361190057600080fd5b803561190e61182e826117e9565b81815260059190911b8201840190848101908c83111561192d57600080fd5b928501925b8284101561195b57833560ff8116811461194c5760008081fd5b82529285019290850190611932565b9650505050606088013591508082111561197457600080fd5b506119818882890161180d565b9150509295509295909350565b6000806000606084860312156119a357600080fd5b83356119ae81611588565b925060208401356119be81611588565b929592945050506040919091013590565b600083516119e181846020880161161b565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611a2881846020880161161b565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611a6f81846020880161161b565b9190910191825250602001919050565b60008351611a9181846020880161161b565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611ad657600080fd5b83861115611ae357600080fd5b5050820193919092039150565b60408152600e60408201527f416176655633576974686472617700000000000000000000000000000000000060608201526080602082015260006116a46080830184611647565b600060208284031215611b4957600080fd5b81516116a481611588565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611b945780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611b945760019490940360031b84901b1690921692915050565b8035602083101561081c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611b945760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611ca557600080fd5b611cad6114f2565b8251611cb88161156a565b81526020830151611cc88161157a565b6020820152604083810151908201526060830151611ce581611588565b6060820152608083015161160f81611588565b600060208284031215611d0a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611d5257611d52611d11565b500390565b600060ff821660ff841680821015611d7157611d71611d11565b90039392505050565b600060208284031215611d8c57600080fd5b81516116a48161157a565b60008251611da981846020870161161b565b919091019291505056fea264697066735822122064d366655cbaf9e34629d9f4c2b835fccb9b0db44d661ac3ded989d5d845167f64736f6c634300080a0033
Deployed Bytecode
0x60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d7578063d4f922dc146103ec578063f24ccbfe1461040157600080fd5b80639864dcdd146103a2578063c579d490146103b757600080fd5b80638cedca71116100a55780638cedca71146103475780638df50f741461036f5780639093410d1461038257600080fd5b80638b835979146102ae5780638bcb62161461033257600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024c5780637b1039991461026157600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac3660046115aa565b610429565b6040516101889190611691565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610562565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b6102016102493660046116ab565b50565b34801561025857600080fd5b5061020161061e565b34801561026d57600080fd5b5061028973bf1cac12db60819bfa71a328282ecbc1d40443aa81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102ba57600080fd5b506102ce6102c93660046117a7565b610708565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561033e57600080fd5b506101d3600181565b34801561035357600080fd5b5061028973d47d8d97cad12a866900eec6cde1962529f2535181565b61021861037d366004611878565b610822565b34801561038e57600080fd5b506102ce61039d3660046116ab565b610a33565b3480156103ae57600080fd5b506101d3607f81565b3480156103c357600080fd5b506102016103d236600461198e565b610a70565b3480156103e357600080fd5b506101d360ff81565b3480156103f857600080fd5b50610218600281565b34801561040d57600080fd5b5061028973e6f9a5c850dbcd12bc64f40d692f537250adec3881565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047891839160f01b906044016119cf565b6040516020818303038152906040529050806104978360200151610bf8565b6040516020016104a8929190611a16565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ec91839190602001611a5d565b604051602081830303815290604052905080826060015160601b604051602001610517929190611a7f565b6040516020818303038152906040529050816020015161055d5780826080015160601b60405160200161054b929190611a7f565b60405160208183030381529060405290505b919050565b60006105746102c93660048185611ac6565b905060006105948260800151836000015184604001518560600151610c2d565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073e6f9a5c850dbcd12bc64f40d692f537250adec38915063f4b24b55906105e8908490600401611af0565b600060405180830381600087803b15801561060257600080fd5b505af1158015610616573d6000803e3d6000fd5b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b89190611b37565b73ffffffffffffffffffffffffffffffffffffffff1614610705576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610741600260008486611ac6565b61074a91611b54565b60f01c8152610790610760600360028587611ac6565b61076991611b9c565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b151560208201526107a5602360038486611ac6565b6107ae91611be2565b60408201526107c1603760238486611ac6565b6107ca91611c1e565b606090811c908201526020810151156107fc5773a97684ead0e402dc232d5a977953df7ecbab3cdb608082015261081c565b61080a604b60378486611ac6565b61081391611c1e565b60601c60808201525b92915050565b60008061086487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a3392505050565b9050610894816000015161ffff168560008151811061088557610885611c64565b60200260200101518786610e73565b61ffff16815260208101516108c7906108ae5760006108b1565b60015b60ff168560018151811061088557610885611c64565b6001146020820152604081015184516108ee91908690600290811061088557610885611c64565b81604001818152505061092181606001518560038151811061091257610912611c64565b60200260200101518786610ef1565b73ffffffffffffffffffffffffffffffffffffffff1660608201526080810151845161095b91908690600490811061091257610912611c64565b73ffffffffffffffffffffffffffffffffffffffff16608082015260208101511561099b5773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201525b6000806109ba8360800151846000015185604001518660600151610c2d565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610a1f9190611691565b60405180910390a250979650505050505050565b6040805160a081018252600080825260208083018290529282018190526060820181905260808201528251909161081c9184018101908401611c93565b3373ffffffffffffffffffffffffffffffffffffffff1673d47d8d97cad12a866900eec6cde1962529f2535173ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190611b37565b73ffffffffffffffffffffffffffffffffffffffff1614610b57576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610bd25760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610bcc573d6000803e3d6000fd5b50505050565b610bf373ffffffffffffffffffffffffffffffffffffffff84168383610fce565b505050565b600081610c0657600061081c565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610c3c8761105b565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd49190611b37565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610d2357610d2073ffffffffffffffffffffffffffffffffffffffff8316876110cc565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190611cf8565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610e1b5780610e0e73ffffffffffffffffffffffffffffffffffffffff8416886110cc565b610e189190611d40565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610ee657610e87846111b5565b15610ebb5781610e96856111d4565b60ff1681518110610ea957610ea9611c64565b602002602001015160001c9450610ee6565b82610ec585611220565b60ff1681518110610ed857610ed8611c64565b602002602001015160001c94505b50835b949350505050565b600060ff841615610ee657610f05846111b5565b15610f395781610f14856111d4565b60ff1681518110610f2757610f27611c64565b602002602001015160601c9450610ee6565b8360ff1660fe1415610f4c575030610ee9565b8360ff1660ff1415610ebb573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc79190611b37565b9050610ee9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610bf390849061126b565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611b37565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561111e575073ffffffffffffffffffffffffffffffffffffffff81163161081c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae9190611cf8565b905061081c565b6000600160ff83161080159061081c5750607f60ff8316111592915050565b60006111df826111b5565b611215576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61081c600183611d57565b6000608060ff83161015611260576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61081c608083611d57565b60006112cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661137c9092919063ffffffff16565b805190915015610bf357808060200190518101906112eb9190611d7a565b610bf3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610ee9848460008560606113918561148a565b6113c7576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516113f09190611d97565b60006040518083038185875af1925050503d806000811461142d576040519150601f19603f3d011682016040523d82523d6000602084013e611432565b606091505b50915091508115611446579150610ee99050565b8051156114565780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113739190611691565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610ee9575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611515576115156114c3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611562576115626114c3565b604052919050565b61ffff8116811461024957600080fd5b801515811461024957600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461024957600080fd5b600060a082840312156115bc57600080fd5b6115c46114f2565b82356115cf8161156a565b815260208301356115df8161157a565b60208201526040838101359082015260608301356115fc81611588565b6060820152608083013561160f81611588565b60808201529392505050565b60005b8381101561163657818101518382015260200161161e565b83811115610bcc5750506000910152565b6000815180845261165f81602086016020860161161b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006116a46020830184611647565b9392505050565b600060208083850312156116be57600080fd5b823567ffffffffffffffff808211156116d657600080fd5b818501915085601f8301126116ea57600080fd5b8135818111156116fc576116fc6114c3565b61172c847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161151b565b9150808252868482850101111561174257600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261177057600080fd5b50813567ffffffffffffffff81111561178857600080fd5b6020830191508360208285010111156117a057600080fd5b9250929050565b600080602083850312156117ba57600080fd5b823567ffffffffffffffff8111156117d157600080fd5b6117dd8582860161175e565b90969095509350505050565b600067ffffffffffffffff821115611803576118036114c3565b5060051b60200190565b600082601f83011261181e57600080fd5b8135602061183361182e836117e9565b61151b565b82815260059290921b8401810191818101908684111561185257600080fd5b8286015b8481101561186d5780358352918301918301611856565b509695505050505050565b60008060008060006080868803121561189057600080fd5b853567ffffffffffffffff808211156118a857600080fd5b6118b489838a0161175e565b90975095506020915087820135818111156118ce57600080fd5b6118da8a828b0161180d565b9550506040880135818111156118ef57600080fd5b8801601f81018a1361190057600080fd5b803561190e61182e826117e9565b81815260059190911b8201840190848101908c83111561192d57600080fd5b928501925b8284101561195b57833560ff8116811461194c5760008081fd5b82529285019290850190611932565b9650505050606088013591508082111561197457600080fd5b506119818882890161180d565b9150509295509295909350565b6000806000606084860312156119a357600080fd5b83356119ae81611588565b925060208401356119be81611588565b929592945050506040919091013590565b600083516119e181846020880161161b565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611a2881846020880161161b565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611a6f81846020880161161b565b9190910191825250602001919050565b60008351611a9181846020880161161b565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611ad657600080fd5b83861115611ae357600080fd5b5050820193919092039150565b60408152600e60408201527f416176655633576974686472617700000000000000000000000000000000000060608201526080602082015260006116a46080830184611647565b600060208284031215611b4957600080fd5b81516116a481611588565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611b945780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611b945760019490940360031b84901b1690921692915050565b8035602083101561081c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611b945760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611ca557600080fd5b611cad6114f2565b8251611cb88161156a565b81526020830151611cc88161157a565b6020820152604083810151908201526060830151611ce581611588565b6060820152608083015161160f81611588565b600060208284031215611d0a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611d5257611d52611d11565b500390565b600060ff821660ff841680821015611d7157611d71611d11565b90039392505050565b600060208284031215611d8c57600080fd5b81516116a48161157a565b60008251611da981846020870161161b565b919091019291505056fea264697066735822122064d366655cbaf9e34629d9f4c2b835fccb9b0db44d661ac3ded989d5d845167f64736f6c634300080a0033
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.