My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0xce7f5db53997aa75924f5f86860d77004c2c69912f60a5555f0f13cb6982144d | 0x60806040 | 14369399 | 614 days 18 hrs ago | 0xba3c7b0b8f29b41f0e841c1ffb1bda8b605830da | IN | Create: AaveV3Withdraw | 0 ETH | 0.001470918797 |
[ 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 Optimistic.Etherscan.io on 2022-07-13 */ // 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 = 0x4200000000000000000000000000000000000006; 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 OptimismAuthAddresses { address internal constant ADMIN_VAULT_ADDR = 0x136b1bEAfff362530F98f10E3D8C38f3a3F3d38C; address internal constant FACTORY_ADDRESS = 0xc19d0F1E2b38AA283E226Ca4044766A43aA7B02b; address internal constant ADMIN_ADDR = 0x98118fD1Da4b3369AEe87778168e97044980632F; } contract AuthHelper is OptimismAuthAddresses { } 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 OptimismActionsUtilAddresses { // TODO: set this address internal constant DFS_REG_CONTROLLER_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant SUB_STORAGE_ADDR = 0xb944291Ed31886b20030d0d4C47c7838d1d9eb97; address internal constant REGISTRY_ADDR = 0xAf707Ee480204Ed6e2640B53cE86F680D28Afcbd; address internal constant DFS_LOGGER_ADDR = 0xFc2f1355296ab7dd98a1260E3Ff5E906999d4Acb; } contract ActionsUtilHelper is OptimismActionsUtilAddresses { } 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 OptimismAaveV3Addresses { address internal constant REWARDS_CONTROLLER_ADDRESS = 0x929EC64c34a17401F460460D4B9390518E5B473e; address internal constant DEFAULT_AAVE_MARKET = 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb; address internal constant TRANSIENT_STORAGE = 0x491f0858Ef9e6987e260587322149Ac33D762e6e; } 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 OptimismAaveV3Addresses { 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 function executeActionDirect(bytes memory _callData) public payable override { Params memory params = parseInputs(_callData); (, bytes memory logData) = _withdraw( params.market, params.assetId, params.amount, params.to ); logger.logActionDirectEvent("AaveV3Withdraw", logData); } function executeActionDirectL2() public payable { Params memory params = decodeInputs(msg.data[4:]); (, bytes memory logData) = _withdraw( params.market, params.assetId, params.amount, params.to ); logger.logActionDirectEvent("AaveV3Withdraw", logData); } /// @inheritdoc ActionBase function actionType() public pure virtual override returns (uint8) { return uint8(ActionType.STANDARD_ACTION); } //////////////////////////// ACTION LOGIC //////////////////////////// /// @notice User withdraws tokens from the Aave protocol /// @param _market Address provider for specific market /// @param _assetId The id of the token to be deposited /// @param _amount Amount of tokens to be withdrawn -> send type(uint).max for whole amount /// @param _to Where the withdrawn tokens will be sent function _withdraw( address _market, uint16 _assetId, uint256 _amount, address _to ) internal returns (uint256, bytes memory) { IPoolV3 lendingPool = getLendingPool(_market); address tokenAddr = lendingPool.getReserveAddressById(_assetId); uint256 tokenBefore; // only need to remember this is _amount is max, no need to waste gas otherwise if (_amount == type(uint256).max) { tokenBefore = tokenAddr.getBalance(_to); } // withdraw underlying tokens from aave and send _to address lendingPool.withdraw(tokenAddr, _amount, _to); // if the input amount is max calc. what was the exact _amount if (_amount == type(uint256).max) { _amount = tokenAddr.getBalance(_to) - tokenBefore; } bytes memory logData = abi.encode(_market, tokenAddr, _amount, _to); return (_amount, logData); } function parseInputs(bytes memory _callData) public pure returns (Params memory params) { params = abi.decode(_callData, (Params)); } function encodeInputs(Params memory params) public pure returns (bytes memory encodedInput) { encodedInput = bytes.concat(this.executeActionDirectL2.selector); encodedInput = bytes.concat(encodedInput, bytes2(params.assetId)); encodedInput = bytes.concat(encodedInput, boolToBytes(params.useDefaultMarket)); encodedInput = bytes.concat(encodedInput, bytes32(params.amount)); encodedInput = bytes.concat(encodedInput, bytes20(params.to)); if (!params.useDefaultMarket) { encodedInput = bytes.concat(encodedInput, bytes20(params.market)); } } function decodeInputs(bytes calldata encodedInput) public 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])); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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
608060405234801561001057600080fd5b50611ea4806100206000396000f3fe60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d9578063d4f922dc146103ee578063f24ccbfe1461040357600080fd5b80639864dcdd146103a4578063c579d490146103b957600080fd5b80638cedca71116100a55780638cedca71146103495780638df50f74146103715780639093410d1461038457600080fd5b80638b835979146102b05780638bcb62161461033457600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024e5780637b1039991461026357600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac366004611665565b61042b565b604051610188919061174c565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610564565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b610201610249366004611766565b610620565b34801561025a57600080fd5b506102016106d6565b34801561026f57600080fd5b5061028b73af707ee480204ed6e2640b53ce86f680d28afcbd81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102bc57600080fd5b506102d06102cb366004611862565b6107c0565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561034057600080fd5b506101d3600181565b34801561035557600080fd5b5061028b73136b1beafff362530f98f10e3d8c38f3a3f3d38c81565b61021861037f366004611933565b6108da565b34801561039057600080fd5b506102d061039f366004611766565b610aeb565b3480156103b057600080fd5b506101d3607f81565b3480156103c557600080fd5b506102016103d4366004611a49565b610b28565b3480156103e557600080fd5b506101d360ff81565b3480156103fa57600080fd5b50610218600281565b34801561040f57600080fd5b5061028b73fc2f1355296ab7dd98a1260e3ff5e906999d4acb81565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047a91839160f01b90604401611a8a565b6040516020818303038152906040529050806104998360200151610cb0565b6040516020016104aa929190611ad1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ee91839190602001611b18565b604051602081830303815290604052905080826060015160601b604051602001610519929190611b3a565b6040516020818303038152906040529050816020015161055f5780826080015160601b60405160200161054d929190611b3a565b60405160208183030381529060405290505b919050565b60006105766102cb3660048185611b81565b905060006105968260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073fc2f1355296ab7dd98a1260e3ff5e906999d4acb915063f4b24b55906105ea908490600401611bab565b600060405180830381600087803b15801561060457600080fd5b505af1158015610618573d6000803e3d6000fd5b505050505050565b600061062b82610aeb565b9050600061064b8260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073fc2f1355296ab7dd98a1260e3ff5e906999d4acb915063f4b24b559061069f908490600401611bab565b600060405180830381600087803b1580156106b957600080fd5b505af11580156106cd573d6000803e3d6000fd5b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673136b1beafff362530f98f10e3d8c38f3a3f3d38c73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611bf2565b73ffffffffffffffffffffffffffffffffffffffff16146107bd576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526107f9600260008486611b81565b61080291611c0f565b60f01c8152610848610818600360028587611b81565b61082191611c57565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b1515602082015261085d602360038486611b81565b61086691611c9d565b6040820152610879603760238486611b81565b61088291611cd9565b606090811c908201526020810151156108b45773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201526108d4565b6108c2604b60378486611b81565b6108cb91611cd9565b60601c60808201525b92915050565b60008061091c87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610aeb92505050565b905061094c816000015161ffff168560008151811061093d5761093d611d1f565b60200260200101518786610f2b565b61ffff168152602081015161097f90610966576000610969565b60015b60ff168560018151811061093d5761093d611d1f565b6001146020820152604081015184516109a691908690600290811061093d5761093d611d1f565b8160400181815250506109d98160600151856003815181106109ca576109ca611d1f565b60200260200101518786610fa9565b73ffffffffffffffffffffffffffffffffffffffff16606082015260808101518451610a139190869060049081106109ca576109ca611d1f565b73ffffffffffffffffffffffffffffffffffffffff166080820152602081015115610a535773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201525b600080610a728360800151846000015185604001518660600151610ce5565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610ad7919061174c565b60405180910390a250979650505050505050565b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825190916108d49184018101908401611d4e565b3373ffffffffffffffffffffffffffffffffffffffff1673136b1beafff362530f98f10e3d8c38f3a3f3d38c73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc29190611bf2565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610c8a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610c84573d6000803e3d6000fd5b50505050565b610cab73ffffffffffffffffffffffffffffffffffffffff84168383611086565b505050565b600081610cbe5760006108d4565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610cf487611113565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190611bf2565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ddb57610dd873ffffffffffffffffffffffffffffffffffffffff831687611184565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190611db3565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ed35780610ec673ffffffffffffffffffffffffffffffffffffffff841688611184565b610ed09190611dfb565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610f9e57610f3f8461126d565b15610f735781610f4e8561128c565b60ff1681518110610f6157610f61611d1f565b602002602001015160001c9450610f9e565b82610f7d856112d8565b60ff1681518110610f9057610f90611d1f565b602002602001015160001c94505b50835b949350505050565b600060ff841615610f9e57610fbd8461126d565b15610ff15781610fcc8561128c565b60ff1681518110610fdf57610fdf611d1f565b602002602001015160601c9450610f9e565b8360ff1660fe1415611004575030610fa1565b8360ff1660ff1415610f73573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f9190611bf2565b9050610fa1565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610cab908490611323565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190611bf2565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156111d6575073ffffffffffffffffffffffffffffffffffffffff8116316108d4565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112669190611db3565b90506108d4565b6000600160ff8316108015906108d45750607f60ff8316111592915050565b60006112978261126d565b6112cd576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4600183611e12565b6000608060ff83161015611318576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4608083611e12565b6000611385826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114349092919063ffffffff16565b805190915015610cab57808060200190518101906113a39190611e35565b610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610fa18484600085606061144985611542565b61147f576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516114a89190611e52565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b509150915081156114fe579150610fa19050565b80511561150e5780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142b919061174c565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610fa1575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156115cd576115cd61157b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561161a5761161a61157b565b604052919050565b61ffff8116811461163257600080fd5b50565b801515811461163257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461163257600080fd5b600060a0828403121561167757600080fd5b61167f6115aa565b823561168a81611622565b8152602083013561169a81611635565b60208201526040838101359082015260608301356116b781611643565b606082015260808301356116ca81611643565b60808201529392505050565b60005b838110156116f15781810151838201526020016116d9565b83811115610c845750506000910152565b6000815180845261171a8160208601602086016116d6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061175f6020830184611702565b9392505050565b6000602080838503121561177957600080fd5b823567ffffffffffffffff8082111561179157600080fd5b818501915085601f8301126117a557600080fd5b8135818111156117b7576117b761157b565b6117e7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115d3565b915080825286848285010111156117fd57600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261182b57600080fd5b50813567ffffffffffffffff81111561184357600080fd5b60208301915083602082850101111561185b57600080fd5b9250929050565b6000806020838503121561187557600080fd5b823567ffffffffffffffff81111561188c57600080fd5b61189885828601611819565b90969095509350505050565b600067ffffffffffffffff8211156118be576118be61157b565b5060051b60200190565b600082601f8301126118d957600080fd5b813560206118ee6118e9836118a4565b6115d3565b82815260059290921b8401810191818101908684111561190d57600080fd5b8286015b848110156119285780358352918301918301611911565b509695505050505050565b60008060008060006080868803121561194b57600080fd5b853567ffffffffffffffff8082111561196357600080fd5b61196f89838a01611819565b909750955060209150878201358181111561198957600080fd5b6119958a828b016118c8565b9550506040880135818111156119aa57600080fd5b8801601f81018a136119bb57600080fd5b80356119c96118e9826118a4565b81815260059190911b8201840190848101908c8311156119e857600080fd5b928501925b82841015611a1657833560ff81168114611a075760008081fd5b825292850192908501906119ed565b96505050506060880135915080821115611a2f57600080fd5b50611a3c888289016118c8565b9150509295509295909350565b600080600060608486031215611a5e57600080fd5b8335611a6981611643565b92506020840135611a7981611643565b929592945050506040919091013590565b60008351611a9c8184602088016116d6565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611ae38184602088016116d6565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611b2a8184602088016116d6565b9190910191825250602001919050565b60008351611b4c8184602088016116d6565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611b9157600080fd5b83861115611b9e57600080fd5b5050820193919092039150565b60408152600e60408201527f4161766556335769746864726177000000000000000000000000000000000000606082015260806020820152600061175f6080830184611702565b600060208284031215611c0457600080fd5b815161175f81611643565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611c4f5780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611c4f5760019490940360031b84901b1690921692915050565b803560208310156108d4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611c4f5760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611d6057600080fd5b611d686115aa565b8251611d7381611622565b81526020830151611d8381611635565b6020820152604083810151908201526060830151611da081611643565b606082015260808301516116ca81611643565b600060208284031215611dc557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611e0d57611e0d611dcc565b500390565b600060ff821660ff841680821015611e2c57611e2c611dcc565b90039392505050565b600060208284031215611e4757600080fd5b815161175f81611635565b60008251611e648184602087016116d6565b919091019291505056fea26469706673582212200abec489366d3a18aafb2df43ca581301a578619a621ff6b1617628e104bf9a764736f6c634300080a0033
Deployed Bytecode
0x60806040526004361061015f5760003560e01c80638b835979116100c05780639864dcdd11610074578063d3c2e7ed11610059578063d3c2e7ed146103d9578063d4f922dc146103ee578063f24ccbfe1461040357600080fd5b80639864dcdd146103a4578063c579d490146103b957600080fd5b80638cedca71116100a55780638cedca71146103495780638df50f74146103715780639093410d1461038457600080fd5b80638b835979146102b05780638bcb62161461033457600080fd5b80632ba38bcb11610117578063389f87ff116100fc578063389f87ff1461023b57806341c0e1b51461024e5780637b1039991461026357600080fd5b80632ba38bcb146102035780632fa13cb81461022657600080fd5b80630f2eee42116101485780630f2eee42146101be578063247492f8146101e55780632895f3aa146101f957600080fd5b806305a363de146101645780630ec5ef8214610191575b600080fd5b34801561017057600080fd5b50610179604081565b60405161ffff90911681526020015b60405180910390f35b34801561019d57600080fd5b506101b16101ac366004611665565b61042b565b604051610188919061174c565b3480156101ca57600080fd5b506101d3608081565b60405160ff9091168152602001610188565b3480156101f157600080fd5b5060016101d3565b610201610564565b005b34801561020f57600080fd5b50610218600181565b604051908152602001610188565b34801561023257600080fd5b506101d3600081565b610201610249366004611766565b610620565b34801561025a57600080fd5b506102016106d6565b34801561026f57600080fd5b5061028b73af707ee480204ed6e2640b53ce86f680d28afcbd81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610188565b3480156102bc57600080fd5b506102d06102cb366004611862565b6107c0565b6040516101889190600060a08201905061ffff835116825260208301511515602083015260408301516040830152606083015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080860151166080850152505092915050565b34801561034057600080fd5b506101d3600181565b34801561035557600080fd5b5061028b73136b1beafff362530f98f10e3d8c38f3a3f3d38c81565b61021861037f366004611933565b6108da565b34801561039057600080fd5b506102d061039f366004611766565b610aeb565b3480156103b057600080fd5b506101d3607f81565b3480156103c557600080fd5b506102016103d4366004611a49565b610b28565b3480156103e557600080fd5b506101d360ff81565b3480156103fa57600080fd5b50610218600281565b34801561040f57600080fd5b5061028b73fc2f1355296ab7dd98a1260e3ff5e906999d4acb81565b604080517f2895f3aa0000000000000000000000000000000000000000000000000000000060208201528151600481830301815260248201909252825161047a91839160f01b90604401611a8a565b6040516020818303038152906040529050806104998360200151610cb0565b6040516020016104aa929190611ad1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252908401519092506104ee91839190602001611b18565b604051602081830303815290604052905080826060015160601b604051602001610519929190611b3a565b6040516020818303038152906040529050816020015161055f5780826080015160601b60405160200161054d929190611b3a565b60405160208183030381529060405290505b919050565b60006105766102cb3660048185611b81565b905060006105968260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073fc2f1355296ab7dd98a1260e3ff5e906999d4acb915063f4b24b55906105ea908490600401611bab565b600060405180830381600087803b15801561060457600080fd5b505af1158015610618573d6000803e3d6000fd5b505050505050565b600061062b82610aeb565b9050600061064b8260800151836000015184604001518560600151610ce5565b6040517ff4b24b5500000000000000000000000000000000000000000000000000000000815290925073fc2f1355296ab7dd98a1260e3ff5e906999d4acb915063f4b24b559061069f908490600401611bab565b600060405180830381600087803b1580156106b957600080fd5b505af11580156106cd573d6000803e3d6000fd5b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1673136b1beafff362530f98f10e3d8c38f3a3f3d38c73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611bf2565b73ffffffffffffffffffffffffffffffffffffffff16146107bd576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526107f9600260008486611b81565b61080291611c0f565b60f01c8152610848610818600360028587611b81565b61082191611c57565b7fff0000000000000000000000000000000000000000000000000000000000000016151590565b1515602082015261085d602360038486611b81565b61086691611c9d565b6040820152610879603760238486611b81565b61088291611cd9565b606090811c908201526020810151156108b45773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201526108d4565b6108c2604b60378486611b81565b6108cb91611cd9565b60601c60808201525b92915050565b60008061091c87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610aeb92505050565b905061094c816000015161ffff168560008151811061093d5761093d611d1f565b60200260200101518786610f2b565b61ffff168152602081015161097f90610966576000610969565b60015b60ff168560018151811061093d5761093d611d1f565b6001146020820152604081015184516109a691908690600290811061093d5761093d611d1f565b8160400181815250506109d98160600151856003815181106109ca576109ca611d1f565b60200260200101518786610fa9565b73ffffffffffffffffffffffffffffffffffffffff16606082015260808101518451610a139190869060049081106109ca576109ca611d1f565b73ffffffffffffffffffffffffffffffffffffffff166080820152602081015115610a535773a97684ead0e402dc232d5a977953df7ecbab3cdb60808201525b600080610a728360800151846000015185604001518660600151610ce5565b6040517f416176655633576974686472617700000000000000000000000000000000000081529193509150600e0160405180910390207f2b6d22f419271bcc89bbac8deec947c664365d6e24d06fef0ca7c325c704dce382604051610ad7919061174c565b60405180910390a250979650505050505050565b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825190916108d49184018101908401611d4e565b3373ffffffffffffffffffffffffffffffffffffffff1673136b1beafff362530f98f10e3d8c38f3a3f3d38c73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc29190611bf2565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610c8a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610c84573d6000803e3d6000fd5b50505050565b610cab73ffffffffffffffffffffffffffffffffffffffff84168383611086565b505050565b600081610cbe5760006108d4565b7f010000000000000000000000000000000000000000000000000000000000000092915050565b600060606000610cf487611113565b6040517f5275179700000000000000000000000000000000000000000000000000000000815261ffff8816600482015290915060009073ffffffffffffffffffffffffffffffffffffffff831690635275179790602401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190611bf2565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ddb57610dd873ffffffffffffffffffffffffffffffffffffffff831687611184565b90505b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820189905287811660448301528416906369328dec906064016020604051808303816000875af1158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190611db3565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff871415610ed35780610ec673ffffffffffffffffffffffffffffffffffffffff841688611184565b610ed09190611dfb565b96505b506040805173ffffffffffffffffffffffffffffffffffffffff998a1660208201529189168282015260608201879052949097166080808901919091528451808903909101815260a090970190935250919492505050565b600060ff841615610f9e57610f3f8461126d565b15610f735781610f4e8561128c565b60ff1681518110610f6157610f61611d1f565b602002602001015160001c9450610f9e565b82610f7d856112d8565b60ff1681518110610f9057610f90611d1f565b602002602001015160001c94505b50835b949350505050565b600060ff841615610f9e57610fbd8461126d565b15610ff15781610fcc8561128c565b60ff1681518110610fdf57610fdf611d1f565b602002602001015160601c9450610f9e565b8360ff1660fe1415611004575030610fa1565b8360ff1660ff1415610f73573073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f9190611bf2565b9050610fa1565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610cab908490611323565b60008173ffffffffffffffffffffffffffffffffffffffff1663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190611bf2565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156111d6575073ffffffffffffffffffffffffffffffffffffffff8116316108d4565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112669190611db3565b90506108d4565b6000600160ff8316108015906108d45750607f60ff8316111592915050565b60006112978261126d565b6112cd576040517fdcc95a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4600183611e12565b6000608060ff83161015611318576040517f866f6e8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d4608083611e12565b6000611385826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114349092919063ffffffff16565b805190915015610cab57808060200190518101906113a39190611e35565b610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6060610fa18484600085606061144985611542565b61147f576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516114a89190611e52565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b509150915081156114fe579150610fa19050565b80511561150e5780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142b919061174c565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610fa1575050151592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156115cd576115cd61157b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561161a5761161a61157b565b604052919050565b61ffff8116811461163257600080fd5b50565b801515811461163257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461163257600080fd5b600060a0828403121561167757600080fd5b61167f6115aa565b823561168a81611622565b8152602083013561169a81611635565b60208201526040838101359082015260608301356116b781611643565b606082015260808301356116ca81611643565b60808201529392505050565b60005b838110156116f15781810151838201526020016116d9565b83811115610c845750506000910152565b6000815180845261171a8160208601602086016116d6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061175f6020830184611702565b9392505050565b6000602080838503121561177957600080fd5b823567ffffffffffffffff8082111561179157600080fd5b818501915085601f8301126117a557600080fd5b8135818111156117b7576117b761157b565b6117e7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115d3565b915080825286848285010111156117fd57600080fd5b8084840185840137600090820190930192909252509392505050565b60008083601f84011261182b57600080fd5b50813567ffffffffffffffff81111561184357600080fd5b60208301915083602082850101111561185b57600080fd5b9250929050565b6000806020838503121561187557600080fd5b823567ffffffffffffffff81111561188c57600080fd5b61189885828601611819565b90969095509350505050565b600067ffffffffffffffff8211156118be576118be61157b565b5060051b60200190565b600082601f8301126118d957600080fd5b813560206118ee6118e9836118a4565b6115d3565b82815260059290921b8401810191818101908684111561190d57600080fd5b8286015b848110156119285780358352918301918301611911565b509695505050505050565b60008060008060006080868803121561194b57600080fd5b853567ffffffffffffffff8082111561196357600080fd5b61196f89838a01611819565b909750955060209150878201358181111561198957600080fd5b6119958a828b016118c8565b9550506040880135818111156119aa57600080fd5b8801601f81018a136119bb57600080fd5b80356119c96118e9826118a4565b81815260059190911b8201840190848101908c8311156119e857600080fd5b928501925b82841015611a1657833560ff81168114611a075760008081fd5b825292850192908501906119ed565b96505050506060880135915080821115611a2f57600080fd5b50611a3c888289016118c8565b9150509295509295909350565b600080600060608486031215611a5e57600080fd5b8335611a6981611643565b92506020840135611a7981611643565b929592945050506040919091013590565b60008351611a9c8184602088016116d6565b7fffff000000000000000000000000000000000000000000000000000000000000939093169190920190815260020192915050565b60008351611ae38184602088016116d6565b7fff00000000000000000000000000000000000000000000000000000000000000939093169190920190815260010192915050565b60008351611b2a8184602088016116d6565b9190910191825250602001919050565b60008351611b4c8184602088016116d6565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000939093169190920190815260140192915050565b60008085851115611b9157600080fd5b83861115611b9e57600080fd5b5050820193919092039150565b60408152600e60408201527f4161766556335769746864726177000000000000000000000000000000000000606082015260806020820152600061175f6080830184611702565b600060208284031215611c0457600080fd5b815161175f81611643565b7fffff0000000000000000000000000000000000000000000000000000000000008135818116916002851015611c4f5780818660020360031b1b83161692505b505092915050565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015611c4f5760019490940360031b84901b1690921692915050565b803560208310156108d4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015611c4f5760149490940360031b84901b1690921692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611d6057600080fd5b611d686115aa565b8251611d7381611622565b81526020830151611d8381611635565b6020820152604083810151908201526060830151611da081611643565b606082015260808301516116ca81611643565b600060208284031215611dc557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611e0d57611e0d611dcc565b500390565b600060ff821660ff841680821015611e2c57611e2c611dcc565b90039392505050565b600060208284031215611e4757600080fd5b815161175f81611635565b60008251611e648184602087016116d6565b919091019291505056fea26469706673582212200abec489366d3a18aafb2df43ca581301a578619a621ff6b1617628e104bf9a764736f6c634300080a0033
Deployed ByteCode Sourcemap
92272:5196:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90765:46;;;;;;;;;;;;90809:2;90765:46;;;;;188:6:1;176:19;;;158:38;;146:2;131:18;90765:46:0;;;;;;;;96288:621;;;;;;;;;;-1:-1:-1;96288:621:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;27679:47::-;;;;;;;;;;;;27723:3;27679:47;;;;;3207:4:1;3195:17;;;3177:36;;3165:2;3150:18;27679:47:0;3035:184:1;94596:126:0;;;;;;;;;;-1:-1:-1;94687:26:0;94596:126;;94208:348;;;:::i;:::-;;90820:37;;;;;;;;;;;;90856:1;90820:37;;;;;3370:25:1;;;3358:2;3343:18;90820:37:0;3224:177:1;28008:42:0;;;;;;;;;;;;28049:1;28008:42;;93827:373;;;;;;:::i;:::-;;:::i;14386:85::-;;;;;;;;;;;;;:::i;27318:65::-;;;;;;;;;;;;26931:42;27318:65;;;;;4429:42:1;4417:55;;;4399:74;;4387:2;4372:18;27318:65:0;4233:246:1;96917:548:0;;;;;;;;;;-1:-1:-1;96917:548:0;;;;;:::i;:::-;;:::i;:::-;;;;;;5390:4:1;5432:3;5421:9;5417:19;5409:27;;5482:6;5473;5467:13;5463:26;5452:9;5445:45;5560:4;5552:6;5548:17;5542:24;5535:32;5528:40;5521:4;5510:9;5506:20;5499:70;5625:4;5617:6;5613:17;5607:24;5600:4;5589:9;5585:20;5578:54;5679:4;5671:6;5667:17;5661:24;5704:42;5802:2;5788:12;5784:21;5777:4;5766:9;5762:20;5755:51;5874:2;5866:4;5858:6;5854:17;5848:24;5844:33;5837:4;5826:9;5822:20;5815:63;;;5250:634;;;;;27838:48:0;;;;;;;;;;;;27885:1;27838:48;;13557:68;;;;;;;;;;;;12408:42;13557:68;;92558:1229;;;;;;:::i;:::-;;:::i;96133:147::-;;;;;;;;;;-1:-1:-1;96133:147:0;;;;;:::i;:::-;;:::i;27893:50::-;;;;;;;;;;;;27940:3;27893:50;;14024:316;;;;;;;;;;-1:-1:-1;14024:316:0;;;;;:::i;:::-;;:::i;27733:47::-;;;;;;;;;;;;27777:3;27733:47;;90864:39;;;;;;;;;;;;90902:1;90864:39;;27392:89;;;;;;;;;;;;27024:42;27392:89;;96288:621;96406:49;;;96419:35;96406:49;;;9843:92:1;96406:49:0;;;;;;;;;9951:11:1;;;96406:49:0;;;96515:14;;96481:50;;96406:49;;96508:22;;;96481:50;;;:::i;:::-;;;;;;;;;;;;;96466:65;;96570:12;96584:36;96596:6;:23;;;96584:11;:36::i;:::-;96557:64;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;96682:13;;;;96557:64;;-1:-1:-1;96647:50:0;;96557:64;;96682:13;96557:64;96647:50;;:::i;:::-;;;;;;;;;;;;;96632:65;;96736:12;96758:6;:9;;;96750:18;;96723:46;;;;;;;;;:::i;:::-;;;;;;;;;;;;;96708:61;;96785:6;:23;;;96780:122;;96853:12;96875:6;:13;;;96867:22;;96840:50;;;;;;;;;:::i;:::-;;;;;;;;;;;;;96825:65;;96780:122;96288:621;;;:::o;94208:348::-;94267:20;94290:26;94303:12;:8;94312:1;94303:8;94267:20;94303:12;:::i;94290:26::-;94267:49;;94330:20;94354:129;94378:6;:13;;;94406:6;:14;;;94435:6;:13;;;94463:6;:9;;;94354;:129::i;:::-;94494:54;;;;;94327:156;;-1:-1:-1;27024:42:0;;-1:-1:-1;94494:27:0;;:54;;94327:156;;94494:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94256:300;;94208:348::o;93827:373::-;93915:20;93938:22;93950:9;93938:11;:22::i;:::-;93915:45;;93974:20;93998:129;94022:6;:13;;;94050:6;:14;;;94079:6;:13;;;94107:6;:9;;;93998;:129::i;:::-;94138:54;;;;;93971:156;;-1:-1:-1;27024:42:0;;-1:-1:-1;94138:27:0;;:54;;93971:156;;94138:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93904:296;;93827:373;:::o;14386:85::-;13898:10;13876:32;;12408:42;13876:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;;;13872:87;;13931:16;;;;;;;;;;;;;;13872:87;14451:10:::1;14430:33;96917:548:::0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97053:17:0;97068:1;97066;97053:12;;:17;:::i;:::-;97046:25;;;:::i;:::-;97039:33;;97022:50;;97109:38;97128:17;97143:1;97141;97128:12;;:17;:::i;:::-;97121:25;;;:::i;:::-;91681:17;;;;;91601:105;97109:38;97083:64;;:23;;;:64;97190:18;97205:2;97203:1;97190:12;;:18;:::i;:::-;97182:27;;;:::i;:::-;97158:13;;;:52;97249:19;97265:2;97262;97249:12;;:19;:::i;:::-;97241:28;;;:::i;:::-;97233:37;;;;97221:9;;;:49;97285:23;;;;97281:177;;;34005:42;97325:13;;;:35;97281:177;;;97425:19;97441:2;97438;97425:12;;:19;:::i;:::-;97417:28;;;:::i;:::-;97409:37;;97393:13;;;:53;97281:177;96917:548;;;;:::o;92558:1229::-;92779:7;92799:20;92822:21;92834:8;;92822:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92822:11:0;;-1:-1:-1;;;92822:21:0:i;:::-;92799:44;;92880:82;92903:6;:14;;;92880:82;;92920:13;92934:1;92920:16;;;;;;;;:::i;:::-;;;;;;;92938:8;92948:13;92880:15;:82::i;:::-;92856:107;;;;93016:23;;;;93000:91;;93016:31;;93046:1;93016:31;;;93042:1;93016:31;93000:91;;93049:13;93063:1;93049:16;;;;;;;;:::i;93000:91::-;93095:1;93000:96;92974:23;;;:122;93139:13;;;;93154:16;;93123:73;;93139:13;93154;;93168:1;;93154:16;;;;;;:::i;93123:73::-;93107:6;:13;;:89;;;;;93219:69;93235:6;:9;;;93246:13;93260:1;93246:16;;;;;;;;:::i;:::-;;;;;;;93264:8;93274:13;93219:15;:69::i;:::-;93207:81;;:9;;;:81;93331:13;;;;93346:16;;93315:73;;93331:13;93346;;93360:1;;93346:16;;;;;;:::i;93315:73::-;93299:89;;:13;;;:89;93405:23;;;;93401:91;;;34005:42;93445:13;;;:35;93401:91;93505:23;93530:20;93554:129;93578:6;:13;;;93606:6;:14;;;93635:6;:13;;;93663:6;:9;;;93554;:129::i;:::-;93699:38;;14767:16:1;14755:29;;93504:179:0;;-1:-1:-1;93504:179:0;-1:-1:-1;14809:2:1;14800:12;93699:38:0;;;;;;;;93729:7;93699:38;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;93763:15:0;92558:1229;-1:-1:-1;;;;;;;92558:1229:0:o;96133:147::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96241:31:0;;-1:-1:-1;;96241:31:0;;;;;;;;;;:::i;14024:316::-;13752:10;13730:32;;12408:42;13730:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;;;13726:87;;13785:16;;;;;;;;;;;;;;13726:87;14146:42:::1;14136:52;::::0;::::1;;14132:201;;;14205:36;::::0;:27:::1;::::0;::::1;::::0;:36;::::1;;;::::0;14233:7;;14205:36:::1;::::0;;;14233:7;14205:27;:36;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;14024:316:::0;;;:::o;14132:201::-:1;14274:47;:27;::::0;::::1;14302:9:::0;14313:7;14274:27:::1;:47::i;:::-;14024:316:::0;;;:::o;91475:118::-;91527:8;91554:1;:31;;91580:4;91554:31;;;91558:12;91547:38;91475:118;-1:-1:-1;;91475:118:0:o;95149:976::-;95293:7;95302:12;95327:19;95349:23;95364:7;95349:14;:23::i;:::-;95403:43;;;;;188:6:1;176:19;;95403:43:0;;;158:38:1;95327:45:0;;-1:-1:-1;95383:17:0;;95403:33;;;;;;131:18:1;;95403:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95383:63;;95459:19;95595:17;95584:7;:28;95580:100;;;95643:25;:20;;;95664:3;95643:20;:25::i;:::-;95629:39;;95580:100;95762:45;;;;;:20;15913:15:1;;;95762:45:0;;;15895:34:1;15945:18;;;15938:34;;;16008:15;;;15988:18;;;15981:43;95762:20:0;;;;;15807:18:1;;95762:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;95907:17;95896:7;:28;95892:110;;;95979:11;95951:25;:20;;;95972:3;95951:20;:25::i;:::-;:39;;;;:::i;:::-;95941:49;;95892:110;-1:-1:-1;96037:44:0;;;16784:42:1;16853:15;;;96037:44:0;;;16835:34:1;16905:15;;;16885:18;;;16878:43;16937:18;;;16930:34;;;17000:15;;;;16980:18;;;;16973:43;;;;96037:44:0;;;;;;;;;;16746:19:1;;;;96037:44:0;;;-1:-1:-1;16930:34:1;;96100:7:0;-1:-1:-1;;;95149:976:0:o;29903:496::-;30082:4;32725:25;;;;30099:267;;30147:27;30165:8;30147:17;:27::i;:::-;30143:212;;;30209:13;30223:24;30238:8;30223:14;:24::i;:::-;30209:39;;;;;;;;;;:::i;:::-;;;;;;;30204:45;;30195:54;;30143:212;;;30307:8;30316:21;30328:8;30316:11;:21::i;:::-;30307:31;;;;;;;;;;:::i;:::-;;;;;;;30299:40;;30290:49;;30143:212;-1:-1:-1;30385:6:0;29903:496;;;;;;;:::o;30788:819::-;30970:7;32725:25;;;;30990:584;;31038:27;31056:8;31038:17;:27::i;:::-;31034:529;;;31112:13;31126:24;31141:8;31126:14;:24::i;:::-;31112:39;;;;;;;;;;:::i;:::-;;;;;;;31095:59;;31086:68;;31034:529;;;31298:8;:15;;31310:3;31298:15;31294:41;;;-1:-1:-1;31330:4:0;31315:20;;31294:41;31376:8;:15;;31388:3;31376:15;31372:67;;;31424:4;31400:37;;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31393:46;;;;7153:211;7297:58;;;17231:42:1;17219:55;;7297:58:0;;;17201:74:1;17291:18;;;;17284:34;;;7297:58:0;;;;;;;;;;17174:18:1;;;;7297:58:0;;;;;;;;;;7320:23;7297:58;;;7270:86;;7290:5;;7270:19;:86::i;90997:153::-;91061:9;91123:7;91100:39;;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;11308:252::-;11385:7;11409:22;;;9569:42;11409:22;11405:148;;;-1:-1:-1;11455:12:0;;;;11448:19;;11405:148;11507:34;;;;;:28;4417:55:1;;;11507:34:0;;;4399:74:1;11507:28:0;;;;;4372:18:1;;11507:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11500:41;;;;32899:165;32962:4;27885:1;32987:31;;;;;;;32986:70;;-1:-1:-1;27940:3:0;33024:31;;;;;32979:77;32899:165;-1:-1:-1;;32899:165:0:o;33212:223::-;33272:5;33296:24;33314:5;33296:17;:24::i;:::-;33290:86;;33344:20;;;;;;;;;;;;;;33290:86;33396:30;27885:1;33396:5;:30;:::i;33580:218::-;33637:5;27723:3;33659:27;;;;33655:89;;;33709:23;;;;;;;;;;;;;;33655:89;33762:27;27723:3;33762:5;:27;:::i;8903:468::-;8984:23;9010:106;9052:4;9010:106;;;;;;;;;;;;;;;;;9018:5;9010:27;;;;:106;;;;;:::i;:::-;9131:17;;8984:132;;-1:-1:-1;9131:21:0;9127:237;;9286:10;9275:30;;;;;;;;;;;;:::i;:::-;9267:85;;;;;;;18212:2:1;9267:85:0;;;18194:21:1;18251:2;18231:18;;;18224:30;18290:34;18270:18;;;18263:62;18361:12;18341:18;;;18334:40;18391:19;;9267:85:0;;;;;;;;3175:230;3312:12;3344:53;3367:6;3375:4;3381:1;3384:12;4298;4329:18;4340:6;4329:10;:18::i;:::-;4323:77;;4371:17;;;;;;;;;;;;;;4323:77;4473:12;4487:23;4514:6;:11;;4533:8;4543:4;4514:34;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4472:76;;;;4563:7;4559:595;;;4594:10;-1:-1:-1;4587:17:0;;-1:-1:-1;4587:17:0;4559:595;4708:17;;:21;4704:439;;4971:10;4965:17;5032:15;5019:10;5015:2;5011:19;5004:44;4704:439;5114:12;5107:20;;;;;;;;;;;:::i;1885:641::-;1945:4;2426:20;;2256:66;2475:23;;;;;;:42;;-1:-1:-1;;2502:15:0;;;2467:51;-1:-1:-1;;1885:641:0:o;207:184:1:-;259:77;256:1;249:88;356:4;353:1;346:15;380:4;377:1;370:15;396:252;468:2;462:9;510:3;498:16;;544:18;529:34;;565:22;;;526:62;523:88;;;591:18;;:::i;:::-;627:2;620:22;396:252;:::o;653:334::-;724:2;718:9;780:2;770:13;;785:66;766:86;754:99;;883:18;868:34;;904:22;;;865:62;862:88;;;930:18;;:::i;:::-;966:2;959:22;653:334;;-1:-1:-1;653:334:1:o;992:117::-;1077:6;1070:5;1066:18;1059:5;1056:29;1046:57;;1099:1;1096;1089:12;1046:57;992:117;:::o;1114:118::-;1200:5;1193:13;1186:21;1179:5;1176:32;1166:60;;1222:1;1219;1212:12;1237:154;1323:42;1316:5;1312:54;1305:5;1302:65;1292:93;;1381:1;1378;1371:12;1396:828;1479:6;1532:3;1520:9;1511:7;1507:23;1503:33;1500:53;;;1549:1;1546;1539:12;1500:53;1575:22;;:::i;:::-;1634:9;1621:23;1653:32;1677:7;1653:32;:::i;:::-;1694:22;;1768:2;1753:18;;1740:32;1781:30;1740:32;1781:30;:::i;:::-;1838:2;1827:14;;1820:31;1911:2;1896:18;;;1883:32;1867:14;;;1860:56;1968:2;1953:18;;1940:32;1981:33;1940:32;1981:33;:::i;:::-;2041:2;2030:14;;2023:31;2106:3;2091:19;;2078:33;2120;2078;2120;:::i;:::-;2180:3;2169:15;;2162:32;2173:5;1396:828;-1:-1:-1;;;1396:828:1:o;2229:258::-;2301:1;2311:113;2325:6;2322:1;2319:13;2311:113;;;2401:11;;;2395:18;2382:11;;;2375:39;2347:2;2340:10;2311:113;;;2442:6;2439:1;2436:13;2433:48;;;-1:-1:-1;;2477:1:1;2459:16;;2452:27;2229:258::o;2492:316::-;2533:3;2571:5;2565:12;2598:6;2593:3;2586:19;2614:63;2670:6;2663:4;2658:3;2654:14;2647:4;2640:5;2636:16;2614:63;:::i;:::-;2722:2;2710:15;2727:66;2706:88;2697:98;;;;2797:4;2693:109;;2492:316;-1:-1:-1;;2492:316:1:o;2813:217::-;2960:2;2949:9;2942:21;2923:4;2980:44;3020:2;3009:9;3005:18;2997:6;2980:44;:::i;:::-;2972:52;2813:217;-1:-1:-1;;;2813:217:1:o;3406:822::-;3474:6;3505:2;3548;3536:9;3527:7;3523:23;3519:32;3516:52;;;3564:1;3561;3554:12;3516:52;3604:9;3591:23;3633:18;3674:2;3666:6;3663:14;3660:34;;;3690:1;3687;3680:12;3660:34;3728:6;3717:9;3713:22;3703:32;;3773:7;3766:4;3762:2;3758:13;3754:27;3744:55;;3795:1;3792;3785:12;3744:55;3831:2;3818:16;3853:2;3849;3846:10;3843:36;;;3859:18;;:::i;:::-;3901:112;4009:2;3940:66;3933:4;3929:2;3925:13;3921:86;3917:95;3901:112;:::i;:::-;3888:125;;4036:2;4029:5;4022:17;4076:7;4071:2;4066;4062;4058:11;4054:20;4051:33;4048:53;;;4097:1;4094;4087:12;4048:53;4152:2;4147;4143;4139:11;4134:2;4127:5;4123:14;4110:45;4196:1;4175:14;;;4171:23;;;4164:34;;;;-1:-1:-1;4179:5:1;3406:822;-1:-1:-1;;;3406:822:1:o;4484:347::-;4535:8;4545:6;4599:3;4592:4;4584:6;4580:17;4576:27;4566:55;;4617:1;4614;4607:12;4566:55;-1:-1:-1;4640:20:1;;4683:18;4672:30;;4669:50;;;4715:1;4712;4705:12;4669:50;4752:4;4744:6;4740:17;4728:29;;4804:3;4797:4;4788:6;4780;4776:19;4772:30;4769:39;4766:59;;;4821:1;4818;4811:12;4766:59;4484:347;;;;;:::o;4836:409::-;4906:6;4914;4967:2;4955:9;4946:7;4942:23;4938:32;4935:52;;;4983:1;4980;4973:12;4935:52;5023:9;5010:23;5056:18;5048:6;5045:30;5042:50;;;5088:1;5085;5078:12;5042:50;5127:58;5177:7;5168:6;5157:9;5153:22;5127:58;:::i;:::-;5204:8;;5101:84;;-1:-1:-1;4836:409:1;-1:-1:-1;;;;4836:409:1:o;6139:183::-;6199:4;6232:18;6224:6;6221:30;6218:56;;;6254:18;;:::i;:::-;-1:-1:-1;6299:1:1;6295:14;6311:4;6291:25;;6139:183::o;6327:662::-;6381:5;6434:3;6427:4;6419:6;6415:17;6411:27;6401:55;;6452:1;6449;6442:12;6401:55;6488:6;6475:20;6514:4;6538:60;6554:43;6594:2;6554:43;:::i;:::-;6538:60;:::i;:::-;6632:15;;;6718:1;6714:10;;;;6702:23;;6698:32;;;6663:12;;;;6742:15;;;6739:35;;;6770:1;6767;6760:12;6739:35;6806:2;6798:6;6794:15;6818:142;6834:6;6829:3;6826:15;6818:142;;;6900:17;;6888:30;;6938:12;;;;6851;;6818:142;;;-1:-1:-1;6978:5:1;6327:662;-1:-1:-1;;;;;;6327:662:1:o;6994:1819::-;7164:6;7172;7180;7188;7196;7249:3;7237:9;7228:7;7224:23;7220:33;7217:53;;;7266:1;7263;7256:12;7217:53;7306:9;7293:23;7335:18;7376:2;7368:6;7365:14;7362:34;;;7392:1;7389;7382:12;7362:34;7431:58;7481:7;7472:6;7461:9;7457:22;7431:58;:::i;:::-;7508:8;;-1:-1:-1;7405:84:1;-1:-1:-1;7562:2:1;;-1:-1:-1;7602:18:1;;;7589:32;7633:16;;;7630:36;;;7662:1;7659;7652:12;7630:36;7685:63;7740:7;7729:8;7718:9;7714:24;7685:63;:::i;:::-;7675:73;;;7801:2;7790:9;7786:18;7773:32;7830:2;7820:8;7817:16;7814:36;;;7846:1;7843;7836:12;7814:36;7869:24;;7924:4;7916:13;;7912:27;-1:-1:-1;7902:55:1;;7953:1;7950;7943:12;7902:55;7989:2;7976:16;8012:60;8028:43;8068:2;8028:43;:::i;8012:60::-;8106:15;;;8188:1;8184:10;;;;8176:19;;8172:28;;;8137:12;;;;8212:19;;;8209:39;;;8244:1;8241;8234:12;8209:39;8268:11;;;;8288:311;8304:6;8299:3;8296:15;8288:311;;;8384:3;8371:17;8432:4;8425:5;8421:16;8414:5;8411:27;8401:125;;8480:1;8509:2;8505;8498:14;8401:125;8539:18;;8321:12;;;;8577;;;;8288:311;;;8618:5;-1:-1:-1;;;;8676:2:1;8661:18;;8648:32;;-1:-1:-1;8692:16:1;;;8689:36;;;8721:1;8718;8711:12;8689:36;;8744:63;8799:7;8788:8;8777:9;8773:24;8744:63;:::i;:::-;8734:73;;;6994:1819;;;;;;;;:::o;9000:456::-;9077:6;9085;9093;9146:2;9134:9;9125:7;9121:23;9117:32;9114:52;;;9162:1;9159;9152:12;9114:52;9201:9;9188:23;9220:31;9245:5;9220:31;:::i;:::-;9270:5;-1:-1:-1;9327:2:1;9312:18;;9299:32;9340:33;9299:32;9340:33;:::i;:::-;9000:456;;9392:7;;-1:-1:-1;;;9446:2:1;9431:18;;;;9418:32;;9000:456::o;9973:438::-;10128:3;10166:6;10160:13;10182:53;10228:6;10223:3;10216:4;10208:6;10204:17;10182:53;:::i;:::-;10308:66;10296:79;;;;10257:16;;;;10282:94;;;10403:1;10392:13;;9973:438;-1:-1:-1;;9973:438:1:o;10416:::-;10571:3;10609:6;10603:13;10625:53;10671:6;10666:3;10659:4;10651:6;10647:17;10625:53;:::i;:::-;10751:66;10739:79;;;;10700:16;;;;10725:94;;;10846:1;10835:13;;10416:438;-1:-1:-1;;10416:438:1:o;10859:370::-;11016:3;11054:6;11048:13;11070:53;11116:6;11111:3;11104:4;11096:6;11092:17;11070:53;:::i;:::-;11145:16;;;;11170:21;;;-1:-1:-1;11218:4:1;11207:16;;10859:370;-1:-1:-1;10859:370:1:o;11234:441::-;11391:3;11429:6;11423:13;11445:53;11491:6;11486:3;11479:4;11471:6;11467:17;11445:53;:::i;:::-;11571:66;11559:79;;;;11520:16;;;;11545:94;;;11666:2;11655:14;;11234:441;-1:-1:-1;;11234:441:1:o;11869:331::-;11974:9;11985;12027:8;12015:10;12012:24;12009:44;;;12049:1;12046;12039:12;12009:44;12078:6;12068:8;12065:20;12062:40;;;12098:1;12095;12088:12;12062:40;-1:-1:-1;;12124:23:1;;;12169:25;;;;;-1:-1:-1;11869:331:1:o;12205:453::-;12453:2;12442:9;12435:21;12492:2;12487;12476:9;12472:18;12465:30;12531:16;12526:2;12515:9;12511:18;12504:44;12586:3;12579:4;12568:9;12564:20;12557:33;12416:4;12607:45;12647:3;12636:9;12632:19;12624:6;12607:45;:::i;12663:251::-;12733:6;12786:2;12774:9;12765:7;12761:23;12757:32;12754:52;;;12802:1;12799;12792:12;12754:52;12834:9;12828:16;12853:31;12878:5;12853:31;:::i;12919:369::-;13077:66;13039:19;;13161:11;;;;13192:1;13184:10;;13181:101;;;13269:2;13263;13256:3;13253:1;13249:11;13246:1;13242:19;13238:28;13234:2;13230:37;13226:46;13217:55;;13181:101;;;12919:369;;;;:::o;13293:::-;13451:66;13413:19;;13535:11;;;;13566:1;13558:10;;13555:101;;;13627:1;13623:11;;;;13620:1;13616:19;13612:28;;;13604:37;13600:46;;;;13293:369;-1:-1:-1;;13293:369:1:o;13667:315::-;13787:19;;13826:2;13818:11;;13815:161;;;13898:66;13887:2;13883:12;;;13880:1;13876:20;13872:93;13861:105;13667:315;;;;:::o;13987:372::-;14146:66;14108:19;;14230:11;;;;14261:2;14253:11;;14250:103;;;14323:2;14319:12;;;;14316:1;14312:20;14308:29;;;14300:38;14296:47;;;;13987:372;-1:-1:-1;;13987:372:1:o;14364:184::-;14416:77;14413:1;14406:88;14513:4;14510:1;14503:15;14537:4;14534:1;14527:15;14823:804;14917:6;14970:3;14958:9;14949:7;14945:23;14941:33;14938:53;;;14987:1;14984;14977:12;14938:53;15013:22;;:::i;:::-;15065:9;15059:16;15084:32;15108:7;15084:32;:::i;:::-;15125:22;;15192:2;15177:18;;15171:25;15205:30;15171:25;15205:30;:::i;:::-;15262:2;15251:14;;15244:31;15328:2;15313:18;;;15307:25;15291:14;;;15284:49;15378:2;15363:18;;15357:25;15391:33;15357:25;15391:33;:::i;:::-;15451:2;15440:14;;15433:31;15509:3;15494:19;;15488:26;15523:33;15488:26;15523:33;:::i;16035:184::-;16105:6;16158:2;16146:9;16137:7;16133:23;16129:32;16126:52;;;16174:1;16171;16164:12;16126:52;-1:-1:-1;16197:16:1;;16035:184;-1:-1:-1;16035:184:1:o;16224:::-;16276:77;16273:1;16266:88;16373:4;16370:1;16363:15;16397:4;16394:1;16387:15;16413:125;16453:4;16481:1;16478;16475:8;16472:34;;;16486:18;;:::i;:::-;-1:-1:-1;16523:9:1;;16413:125::o;17560:195::-;17598:4;17635;17632:1;17628:12;17667:4;17664:1;17660:12;17692:3;17687;17684:12;17681:38;;;17699:18;;:::i;:::-;17736:13;;;17560:195;-1:-1:-1;;;17560:195:1:o;17760:245::-;17827:6;17880:2;17868:9;17859:7;17855:23;17851:32;17848:52;;;17896:1;17893;17886:12;17848:52;17928:9;17922:16;17947:28;17969:5;17947:28;:::i;18421:274::-;18550:3;18588:6;18582:13;18604:53;18650:6;18645:3;18638:4;18630:6;18626:17;18604:53;:::i;:::-;18673:16;;;;;18421:274;-1:-1:-1;;18421:274:1:o
Swarm Source
ipfs://0abec489366d3a18aafb2df43ca581301a578619a621ff6b1617628e104bf9a7
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.