Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 13423554 | 1083 days ago | IN | 0 ETH | 0.20673675 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FLBalancer
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-10-15 */ // SPDX-License-Identifier: MIT pragma solidity =0.7.6; pragma experimental ABIEncoderV2; interface IAsset { } interface IVault{ function joinPool( bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request ) external payable; struct JoinPoolRequest { IAsset[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } function exitPool( bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request ) external; struct ExitPoolRequest { IAsset[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function getPoolTokens(bytes32 poolId) external view returns ( address[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock ); } contract MainnetBalancerV2Addresses { address internal constant VAULT_ADDR = 0xBA12222222228d8Ba445958a75a0704d566BF2C8; address internal constant MERKLE_REEDEM_ADDR = 0x6d19b2bF3A36A61530909Ae65445a906D98A2Fa8; address internal constant balToken = 0xba100000625a3754423978a60c9317c58a424e3D; } contract BalancerV2Helper is MainnetBalancerV2Addresses{ IVault public constant vault = IVault(VAULT_ADDR); string public constant ADDR_MUST_NOT_BE_ZERO = "Address to which tokens will be sent to can't be burn address"; function _getPoolAddress(bytes32 poolId) internal pure returns (address) { // 12 byte logical shift left to remove the nonce and specialization setting. We don't need to mask, // since the logical shift already sets the upper bits to zero. return address(uint256(poolId) >> (12 * 8)); } } abstract contract IDFSRegistry { function getAddr(bytes32 _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; } interface IERC20 { 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); function decimals() external view returns (uint256 digits); event Approval(address indexed _owner, address indexed _spender, uint256 _value); } library Address { 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 { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } 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) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue( address target, bytes memory data, uint256 weiValue, string memory errorMessage ) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // 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"); } } } contract MainnetAuthAddresses { address internal constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD; address internal constant FACTORY_ADDRESS = 0x5a15566417e6C1c9546523066500bDDBc53F88C7; address internal constant ADMIN_ADDR = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9; // USED IN ADMIN VAULT CONSTRUCTOR } contract AuthHelper is MainnetAuthAddresses { } contract AdminVault is AuthHelper { address public owner; address public admin; 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 { require(admin == msg.sender, "msg.sender not admin"); owner = _owner; } /// @notice Admin is able to set new admin /// @param _admin Address of multisig that becomes new admin function changeAdmin(address _admin) public { require(admin == msg.sender, "msg.sender not admin"); admin = _admin; } } contract AdminAuth is AuthHelper { using SafeERC20 for IERC20; AdminVault public constant adminVault = AdminVault(ADMIN_VAULT_ADDR); modifier onlyOwner() { require(adminVault.owner() == msg.sender, "msg.sender not owner"); _; } modifier onlyAdmin() { require(adminVault.admin() == msg.sender, "msg.sender not admin"); _; } /// @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 DefisaverLogger { event LogEvent( address indexed contractAddress, address indexed caller, string indexed logName, bytes data ); // solhint-disable-next-line func-name-mixedcase function Log( address _contract, address _caller, string memory _logName, bytes memory _data ) public { emit LogEvent(_contract, _caller, _logName, _data); } } contract MainnetCoreAddresses { address internal constant DEFI_SAVER_LOGGER_ADDR = 0x5c55B921f590a89C1Ebe84dF170E655a82b62126; address internal constant REGISTRY_ADDR = 0xD6049E1F5F3EfF1F921f5532aF1A1632bA23929C; address internal constant PROXY_AUTH_ADDR = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF; } contract CoreHelper is MainnetCoreAddresses { } contract DFSRegistry is AdminAuth, CoreHelper { DefisaverLogger public constant logger = DefisaverLogger( DEFI_SAVER_LOGGER_ADDR ); string public constant ERR_ENTRY_ALREADY_EXISTS = "Entry id already exists"; string public constant ERR_ENTRY_NON_EXISTENT = "Entry id doesn't exists"; string public constant ERR_ENTRY_NOT_IN_CHANGE = "Entry not in change process"; string public constant ERR_WAIT_PERIOD_SHORTER = "New wait period must be bigger"; string public constant ERR_CHANGE_NOT_READY = "Change not ready yet"; string public constant ERR_EMPTY_PREV_ADDR = "Previous addr is 0"; string public constant ERR_ALREADY_IN_CONTRACT_CHANGE = "Already in contract change"; string public constant ERR_ALREADY_IN_WAIT_PERIOD_CHANGE = "Already in wait period change"; struct Entry { address contractAddr; uint256 waitPeriod; uint256 changeStartTime; bool inContractChange; bool inWaitPeriodChange; bool exists; } mapping(bytes32 => Entry) public entries; mapping(bytes32 => address) public previousAddresses; mapping(bytes32 => address) public pendingAddresses; mapping(bytes32 => 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(bytes32 _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(bytes32 _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( bytes32 _id, address _contractAddr, uint256 _waitPeriod ) public onlyOwner { require(!entries[_id].exists, ERR_ENTRY_ALREADY_EXISTS); entries[_id] = Entry({ contractAddr: _contractAddr, waitPeriod: _waitPeriod, changeStartTime: 0, inContractChange: false, inWaitPeriodChange: false, exists: true }); // Remember tha address so we can revert back to old addr if needed previousAddresses[_id] = _contractAddr; logger.Log( address(this), msg.sender, "AddNewContract", abi.encode(_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(bytes32 _id) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(previousAddresses[_id] != address(0), ERR_EMPTY_PREV_ADDR); address currentAddr = entries[_id].contractAddr; entries[_id].contractAddr = previousAddresses[_id]; logger.Log( address(this), msg.sender, "RevertToPreviousAddress", abi.encode(_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(bytes32 _id, address _newContractAddr) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(!entries[_id].inWaitPeriodChange, ERR_ALREADY_IN_WAIT_PERIOD_CHANGE); entries[_id].changeStartTime = block.timestamp; // solhint-disable-line entries[_id].inContractChange = true; pendingAddresses[_id] = _newContractAddr; logger.Log( address(this), msg.sender, "StartContractChange", abi.encode(_id, entries[_id].contractAddr, _newContractAddr) ); } /// @notice Changes new contract address, correct time must have passed /// @param _id Id of contract function approveContractChange(bytes32 _id) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(entries[_id].inContractChange, ERR_ENTRY_NOT_IN_CHANGE); require( block.timestamp >= (entries[_id].changeStartTime + entries[_id].waitPeriod), // solhint-disable-line ERR_CHANGE_NOT_READY ); 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; logger.Log( address(this), msg.sender, "ApproveContractChange", abi.encode(_id, oldContractAddr, entries[_id].contractAddr) ); } /// @notice Cancel pending change /// @param _id Id of contract function cancelContractChange(bytes32 _id) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(entries[_id].inContractChange, ERR_ENTRY_NOT_IN_CHANGE); address oldContractAddr = pendingAddresses[_id]; pendingAddresses[_id] = address(0); entries[_id].inContractChange = false; entries[_id].changeStartTime = 0; logger.Log( address(this), msg.sender, "CancelContractChange", abi.encode(_id, oldContractAddr, entries[_id].contractAddr) ); } /// @notice Starts the change for waitPeriod /// @param _id Id of contract /// @param _newWaitPeriod New wait time function startWaitPeriodChange(bytes32 _id, uint256 _newWaitPeriod) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(!entries[_id].inContractChange, ERR_ALREADY_IN_CONTRACT_CHANGE); pendingWaitTimes[_id] = _newWaitPeriod; entries[_id].changeStartTime = block.timestamp; // solhint-disable-line entries[_id].inWaitPeriodChange = true; logger.Log( address(this), msg.sender, "StartWaitPeriodChange", abi.encode(_id, _newWaitPeriod) ); } /// @notice Changes new wait period, correct time must have passed /// @param _id Id of contract function approveWaitPeriodChange(bytes32 _id) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(entries[_id].inWaitPeriodChange, ERR_ENTRY_NOT_IN_CHANGE); require( block.timestamp >= (entries[_id].changeStartTime + entries[_id].waitPeriod), // solhint-disable-line ERR_CHANGE_NOT_READY ); uint256 oldWaitTime = entries[_id].waitPeriod; entries[_id].waitPeriod = pendingWaitTimes[_id]; entries[_id].inWaitPeriodChange = false; entries[_id].changeStartTime = 0; pendingWaitTimes[_id] = 0; logger.Log( address(this), msg.sender, "ApproveWaitPeriodChange", abi.encode(_id, oldWaitTime, entries[_id].waitPeriod) ); } /// @notice Cancel wait period change /// @param _id Id of contract function cancelWaitPeriodChange(bytes32 _id) public onlyOwner { require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT); require(entries[_id].inWaitPeriodChange, ERR_ENTRY_NOT_IN_CHANGE); uint256 oldWaitPeriod = pendingWaitTimes[_id]; pendingWaitTimes[_id] = 0; entries[_id].inWaitPeriodChange = false; entries[_id].changeStartTime = 0; logger.Log( address(this), msg.sender, "CancelWaitPeriodChange", abi.encode(_id, oldWaitPeriod, entries[_id].waitPeriod) ); } } contract MainnetActionsUtilAddresses { address internal constant DFS_REG_CONTROLLER_ADDR = 0xF8f8B3C98Cf2E63Df3041b73f80F362a4cf3A576; address internal constant REGISTRY_ADDR = 0xD6049E1F5F3EfF1F921f5532aF1A1632bA23929C; address internal constant DFS_LOGGER_ADDR = 0x5c55B921f590a89C1Ebe84dF170E655a82b62126; } contract ActionsUtilHelper is MainnetActionsUtilAddresses { } abstract contract ActionBase is AdminAuth, ActionsUtilHelper { DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR); DefisaverLogger public constant logger = DefisaverLogger( DFS_LOGGER_ADDR ); string public constant ERR_SUB_INDEX_VALUE = "Wrong sub index value"; string public constant ERR_RETURN_INDEX_VALUE = "Wrong return index value"; /// @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, CUSTOM_ACTION } /// @notice Parses inputs and runs the implemented action through a proxy /// @dev Is called by the TaskExecutor 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, bytes[] 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, bytes[] memory _subData, bytes32[] memory _returnValues ) internal pure returns (uint) { if (isReplaceable(_mapType)) { if (isReturnInjection(_mapType)) { _param = uint(_returnValues[getReturnIndex(_mapType)]); } else { _param = abi.decode(_subData[getSubIndex(_mapType)], (uint)); } } 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, bytes[] memory _subData, bytes32[] memory _returnValues ) internal pure returns (address) { if (isReplaceable(_mapType)) { if (isReturnInjection(_mapType)) { _param = address(bytes20((_returnValues[getReturnIndex(_mapType)]))); } else { _param = abi.decode(_subData[getSubIndex(_mapType)], (address)); } } 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, bytes[] memory _subData, bytes32[] memory _returnValues ) internal pure returns (bytes32) { if (isReplaceable(_mapType)) { if (isReturnInjection(_mapType)) { _param = (_returnValues[getReturnIndex(_mapType)]); } else { _param = abi.decode(_subData[getSubIndex(_mapType)], (bytes32)); } } 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) { require(isReturnInjection(_type), ERR_SUB_INDEX_VALUE); 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) { require(_type >= SUB_MIN_INDEX_VALUE, ERR_RETURN_INDEX_VALUE); return (_type - SUB_MIN_INDEX_VALUE); } } contract StrategyData { struct Template { string name; bytes32[] triggerIds; bytes32[] actionIds; uint8[][] paramMapping; } struct Task { string name; bytes[][] callData; bytes[][] subData; bytes32[] actionIds; uint8[][] paramMapping; } struct Strategy { uint templateId; address proxy; bytes[][] subData; bytes[][] triggerData; bool active; uint posInUserArr; } } interface IFlashLoanRecipient { /** * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient. * * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the * Vault, or else the entire flash loan will revert. * * `userData` is the same value passed in the `IVault.flashLoan` call. */ function receiveFlashLoan( address[] memory tokens, uint256[] memory amounts, uint256[] memory feeAmounts, bytes memory userData ) external; } interface IFlashLoans { function flashLoan( address recipient, address[] memory tokens, uint256[] memory amounts, bytes memory userData ) external; } abstract contract IDSProxy { // function execute(bytes memory _code, bytes memory _data) // public // payable // virtual // returns (address, bytes32); function execute(address _target, bytes memory _data) public payable virtual returns (bytes32); function setCache(address _cacheAddr) public payable virtual returns (bool); function owner() public view virtual returns (address); } abstract contract IFLParamGetter { function getFlashLoanParams(bytes memory _data) public view virtual returns ( address[] memory tokens, uint256[] memory amount, uint256[] memory modes ); } 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 TokenUtils { using SafeERC20 for IERC20; address public constant WETH_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; function approveToken( address _tokenAddr, address _to, uint256 _amount ) internal { if (_tokenAddr == ETH_ADDR) return; if (IERC20(_tokenAddr).allowance(address(this), _to) < _amount) { IERC20(_tokenAddr).safeApprove(_to, _amount); } } function pullTokensIfNeeded( address _token, address _from, uint256 _amount ) internal returns (uint256) { // handle max uint amount if (_amount == type(uint256).max) { _amount = getBalance(_token, _from); } if (_from != address(0) && _from != address(this) && _token != ETH_ADDR && _amount != 0) { IERC20(_token).safeTransferFrom(_from, address(this), _amount); } return _amount; } function withdrawTokens( address _token, address _to, uint256 _amount ) internal returns (uint256) { if (_amount == type(uint256).max) { _amount = getBalance(_token, address(this)); } if (_to != address(0) && _to != address(this) && _amount != 0) { if (_token != ETH_ADDR) { IERC20(_token).safeTransfer(_to, _amount); } else { payable(_to).transfer(_amount); } } 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 ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } contract FLBalancer is ActionBase, ReentrancyGuard, IFlashLoanRecipient, BalancerV2Helper { using TokenUtils for address; using SafeMath for uint256; /// @dev Function sig of TaskExecutor._executeActionsFromFL() bytes4 public constant CALLBACK_SELECTOR = 0xd6741b9e; bytes32 constant TASK_EXECUTOR_ID = keccak256("TaskExecutor"); bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); struct Params { address[] tokens; // Tokens to flash borrow uint256[] amounts; // Token amounts address flParamGetterAddr; // On-chain contract used for piping FL action parameters bytes flParamGetterData; // Data to supply to flParamGetter } function executeAction( bytes[] memory _callData, bytes[] memory, uint8[] memory, bytes32[] memory ) public override payable returns (bytes32) { Params memory params = parseInputs(_callData); if (params.flParamGetterAddr != address(0)) { (params.tokens, params.amounts,) = IFLParamGetter(params.flParamGetterAddr).getFlashLoanParams(params.flParamGetterData); } bytes memory taskData = _callData[_callData.length - 1]; uint256 amount = _flBalancer(params, taskData); return bytes32(amount); } // solhint-disable-next-line no-empty-blocks function executeActionDirect(bytes[] memory _callData) public override payable {} /// @inheritdoc ActionBase function actionType() public override pure returns (uint8) { return uint8(ActionType.FL_ACTION); } /// @notice Gets a FL from Balancer and returns back the execution to the action address function _flBalancer(Params memory _params, bytes memory _taskData) internal returns (uint256) { IFlashLoans(VAULT_ADDR).flashLoan( address(this), _params.tokens, _params.amounts, _taskData ); logger.Log( address(this), msg.sender, "FLBalancer", abi.encode( _params ) ); return _params.amounts[0]; } /// @notice Balancer FL callback function that formats and calls back TaskExecutor function receiveFlashLoan( address[] memory _tokens, uint256[] memory _amounts, uint256[] memory _feeAmounts, bytes memory _userData ) external override nonReentrant { require(msg.sender == VAULT_ADDR, "Untrusted lender"); (StrategyData.Task memory currTask, address proxy) = abi.decode(_userData, (StrategyData.Task, address)); for (uint256 i = 0; i < _tokens.length; i++) { _tokens[i].withdrawTokens(proxy, _amounts[i]); } address payable taskExecutor = payable(registry.getAddr(TASK_EXECUTOR_ID)); // call Action execution IDSProxy(proxy).execute{value: address(this).balance}( taskExecutor, abi.encodeWithSelector(CALLBACK_SELECTOR, currTask, _amounts[0].add(_feeAmounts[0])) ); for (uint256 i = 0; i < _tokens.length; i++) { uint256 paybackAmount = _amounts[i].add(_feeAmounts[i]); require(_tokens[i].getBalance(address(this)) == paybackAmount, "Wrong payback amount"); _tokens[i].withdrawTokens(address(VAULT_ADDR), paybackAmount); } } function parseInputs(bytes[] memory _callData) public pure returns (Params memory params) { params = abi.decode(_callData[0], (Params)); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"ADDR_MUST_NOT_BE_ZERO","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CALLBACK_SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CALLBACK_SUCCESS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_RETURN_INDEX_VALUE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_SUB_INDEX_VALUE","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"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":"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":"_callData","type":"bytes[]"},{"internalType":"bytes[]","name":"","type":"bytes[]"},{"internalType":"uint8[]","name":"","type":"uint8[]"},{"internalType":"bytes32[]","name":"","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":"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":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"flParamGetterAddr","type":"address"},{"internalType":"bytes","name":"flParamGetterData","type":"bytes"}],"internalType":"struct FLBalancer.Params","name":"params","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_feeAmounts","type":"uint256[]"},{"internalType":"bytes","name":"_userData","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract DFSRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IVault","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
608060405234801561001057600080fd5b5060016000556120c0806100256000396000f3fe60806040526004361061016a5760003560e01c80639864dcdd116100cb578063e910afb21161007f578063f829822d11610059578063f829822d1461035f578063f8e2fb0014610374578063fbfa77cf146103895761016a565b8063e910afb214610308578063f04f27071461032a578063f24ccbfe1461034a5761016a565b8063c579d490116100b0578063c579d490146102c0578063ca5ff780146102e0578063d3c2e7ed146102f35761016a565b80639864dcdd146102895780639ce3e9191461029e5761016a565b806341c0e1b5116101225780638237e538116101075780638237e5381461023d5780638bcb62161461025f5780638cedca71146102745761016a565b806341c0e1b5146102065780637b1039991461021b5761016a565b80631afd15be116101535780631afd15be146101c7578063247492f8146101dc5780632fa13cb8146101f15761016a565b80630336fd901461016f5780630f2eee42146101a5575b600080fd5b34801561017b57600080fd5b5061018f61018a366004611639565b61039e565b60405161019c9190611e54565b60405180910390f35b3480156101b157600080fd5b506101ba6103d4565b60405161019c9190611f87565b6101da6101d5366004611639565b6103d9565b005b3480156101e857600080fd5b506101ba6103dc565b3480156101fd57600080fd5b506101ba6103e1565b34801561021257600080fd5b506101da6103e6565b34801561022757600080fd5b506102306104a7565b60405161019c9190611b22565b34801561024957600080fd5b506102526104bf565b60405161019c9190611c2d565b34801561026b57600080fd5b506101ba6104e3565b34801561028057600080fd5b506102306104e8565b34801561029557600080fd5b506101ba610500565b3480156102aa57600080fd5b506102b3610505565b60405161019c9190611c36565b3480156102cc57600080fd5b506101da6102db36600461146e565b610529565b6102526102ee36600461166c565b610658565b3480156102ff57600080fd5b506101ba610741565b34801561031457600080fd5b5061031d610746565b60405161019c9190611c63565b34801561033657600080fd5b506101da610345366004611532565b61077f565b34801561035657600080fd5b50610230610afe565b34801561036b57600080fd5b5061031d610b16565b34801561038057600080fd5b5061031d610b32565b34801561039557600080fd5b50610230610b6b565b6103a66110ac565b816000815181106103b357fe5b60200260200101518060200190518101906103ce919061179d565b92915050565b608081565b50565b600090565b600081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561043d57600080fd5b505afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104759190611452565b6001600160a01b0316146104a45760405162461bcd60e51b815260040161049b90611d1b565b60405180910390fd5b33ff5b73d6049e1f5f3eff1f921f5532af1a1632ba23929c81565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b600181565b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b607f81565b7fd6741b9e0000000000000000000000000000000000000000000000000000000081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561058057600080fd5b505afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190611452565b6001600160a01b0316146105de5760405162461bcd60e51b815260040161049b90611cad565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038416141561063f576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610639573d6000803e3d6000fd5b50610653565b6106536001600160a01b0384168383610b83565b505050565b6000806106648661039e565b60408101519091506001600160a01b03161561070b5780604001516001600160a01b0316630ae1cc8e82606001516040518263ffffffff1660e01b81526004016106ae9190611c63565b60006040518083038186803b1580156106c657600080fd5b505afa1580156106da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261070291908101906114ae565b50602083015281525b60008660018851038151811061071d57fe5b6020026020010151905060006107338383610c06565b93505050505b949350505050565b60ff81565b6040518060400160405280601881526020017f57726f6e672072657475726e20696e6465782076616c7565000000000000000081525081565b600260005414156107a25760405162461bcd60e51b815260040161049b90611e1d565b60026000553373ba12222222228d8ba445958a75a0704d566bf2c8146107da5760405162461bcd60e51b815260040161049b90611ce4565b600080828060200190518101906107f1919061185f565b9150915060005b865181101561084e576108458287838151811061081157fe5b602002602001015189848151811061082557fe5b60200260200101516001600160a01b0316610d4c9092919063ffffffff16565b506001016107f8565b506040517f4ccee9b600000000000000000000000000000000000000000000000000000000815260009073d6049e1f5f3eff1f921f5532af1a1632ba23929c90634ccee9b6906108c2907fcec38b05fe06a488e2de01744d7ff3b8ac89eb607661ed3d7a4b16544d0c7a7290600401611c2d565b60206040518083038186803b1580156108da57600080fd5b505afa1580156108ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109129190611452565b9050816001600160a01b0316631cff79cd478363d6741b9e60e01b876109698b60008151811061093e57fe5b60200260200101518d60008151811061095357fe5b6020026020010151610e1290919063ffffffff16565b60405160240161097a929190611ebf565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526109ed9291600401611b36565b6020604051808303818588803b158015610a0657600080fd5b505af1158015610a1a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a3f9190611785565b5060005b8751811015610aef576000610a71878381518110610a5d57fe5b602002602001015189848151811061095357fe5b905080610aa3308b8581518110610a8457fe5b60200260200101516001600160a01b0316610e3e90919063ffffffff16565b14610ac05760405162461bcd60e51b815260040161049b90611d52565b610ae573ba12222222228d8ba445958a75a0704d566bf2c8828b858151811061082557fe5b5050600101610a43565b50506001600055505050505050565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6040518060600160405280603d815260200161204e603d913981565b6040518060400160405280601581526020017f57726f6e672073756220696e6465782076616c7565000000000000000000000081525081565b73ba12222222228d8ba445958a75a0704d566bf2c881565b6106538363a9059cbb60e01b8484604051602401610ba2929190611c14565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610f12565b815160208301516040517f5c38449e00000000000000000000000000000000000000000000000000000000815260009273ba12222222228d8ba445958a75a0704d566bf2c892635c38449e92610c6492309290918890600401611bc1565b600060405180830381600087803b158015610c7e57600080fd5b505af1158015610c92573d6000803e3d6000fd5b50505050735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce50303386604051602001610ccc9190611e54565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610cf993929190611b58565b600060405180830381600087803b158015610d1357600080fd5b505af1158015610d27573d6000803e3d6000fd5b505050508260200151600081518110610d3c57fe5b6020026020010151905092915050565b6000600019821415610d6557610d628430610e3e565b91505b6001600160a01b03831615801590610d8657506001600160a01b0383163014155b8015610d9157508115155b15610e0b576001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610dd357610dce6001600160a01b0385168484610b83565b610e0b565b6040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015610e09573d6000803e3d6000fd5b505b5092915050565b600082820183811015610e375760405162461bcd60e51b815260040161049b90611c76565b9392505050565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610e7657506001600160a01b038116316103ce565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038416906370a0823190610ebb908590600401611b22565b60206040518083038186803b158015610ed357600080fd5b505afa158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0b9190611785565b90506103ce565b6000610f67826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610fa19092919063ffffffff16565b8051909150156106535780806020019051810190610f859190611765565b6106535760405162461bcd60e51b815260040161049b90611dc0565b606061073984846000856060610fb68561106e565b610fd25760405162461bcd60e51b815260040161049b90611d89565b600080866001600160a01b03168587604051610fee9190611b06565b60006040518083038185875af1925050503d806000811461102b576040519150601f19603f3d011682016040523d82523d6000602084013e611030565b606091505b509150915081156110445791506107399050565b8051156110545780518082602001fd5b8360405162461bcd60e51b815260040161049b9190611c63565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906110a257508115155b925050505b919050565b6040518060800160405280606081526020016060815260200160006001600160a01b03168152602001606081525090565b80516110a781612029565b600082601f8301126110f8578081fd5b8151602061110d61110883611fb9565b611f95565b8281528181019085830183850287018401881015611129578586fd5b855b8581101561115057815161113e81612029565b8452928401929084019060010161112b565b5090979650505050505050565b600082601f83011261116d578081fd5b8151602061117d61110883611fb9565b82815281810190858301855b85811015611150578151880189603f8201126111a3578788fd5b858101516111b361110882611fb9565b81815287810190604084018b5b848110156111ea576111d88f6040845189010161140f565b8452928a0192908a01906001016111c0565b505087525050509284019290840190600101611189565b600082601f830112611211578081fd5b8151602061122161110883611fb9565b82815281810190858301855b85811015611150578151880189603f820112611247578788fd5b85810151604061125961110883611fb9565b828152888101908483018a8502860184018f1015611275578c8dfd5b8c95505b848610156112a3578051935061128e8461203e565b83835260019590950194918a01918a01611279565b50885250505093850193509084019060010161122d565b600082601f8301126112ca578081fd5b813560206112da61110883611fb9565b82815281810190858301838502870184018810156112f6578586fd5b855b85811015611150578135845292840192908401906001016112f8565b600082601f830112611324578081fd5b8151602061133461110883611fb9565b8281528181019085830183850287018401881015611350578586fd5b855b8581101561115057815184529284019290840190600101611352565b600082601f83011261137e578081fd5b8135602061138e61110883611fb9565b82815281810190858301855b85811015611150576113b1898684358b01016113c3565b8452928401929084019060010161139a565b600082601f8301126113d3578081fd5b81356113e161110882611fd7565b8181528460208386010111156113f5578283fd5b816020850160208301379081016020019190915292915050565b600082601f83011261141f578081fd5b815161142d61110882611fd7565b818152846020838601011115611441578283fd5b610739826020830160208701611ff9565b600060208284031215611463578081fd5b8151610e3781612029565b600080600060608486031215611482578182fd5b833561148d81612029565b9250602084013561149d81612029565b929592945050506040919091013590565b6000806000606084860312156114c2578081fd5b835167ffffffffffffffff808211156114d9578283fd5b6114e5878388016110e8565b945060208601519150808211156114fa578283fd5b61150687838801611314565b9350604086015191508082111561151b578283fd5b5061152886828701611314565b9150509250925092565b60008060008060808587031215611547578182fd5b843567ffffffffffffffff8082111561155e578384fd5b818701915087601f830112611571578384fd5b8135602061158161110883611fb9565b82815281810190858301838502870184018d101561159d578889fd5b8896505b848710156115c85780356115b481612029565b8352600196909601959183019183016115a1565b50985050880135925050808211156115de578384fd5b6115ea888389016112ba565b945060408701359150808211156115ff578384fd5b61160b888389016112ba565b93506060870135915080821115611620578283fd5b5061162d878288016113c3565b91505092959194509250565b60006020828403121561164a578081fd5b813567ffffffffffffffff811115611660578182fd5b6107398482850161136e565b60008060008060808587031215611681578182fd5b843567ffffffffffffffff80821115611698578384fd5b6116a48883890161136e565b95506020915081870135818111156116ba578485fd5b6116c689828a0161136e565b9550506040870135818111156116da578485fd5b8701601f810189136116ea578485fd5b80356116f861110882611fb9565b81815284810190838601868402850187018d1015611714578889fd5b8894505b8385101561173f57803561172b8161203e565b835260019490940193918601918601611718565b5096505050506060870135915080821115611758578283fd5b5061162d878288016112ba565b600060208284031215611776578081fd5b81518015158114610e37578182fd5b600060208284031215611796578081fd5b5051919050565b6000602082840312156117ae578081fd5b815167ffffffffffffffff808211156117c5578283fd5b90830190608082860312156117d8578283fd5b6117e26080611f95565b8251828111156117f0578485fd5b6117fc878286016110e8565b825250602083015182811115611810578485fd5b61181c87828601611314565b60208301525061182e604084016110dd565b6040820152606083015182811115611844578485fd5b6118508782860161140f565b60608301525095945050505050565b60008060408385031215611871578182fd5b825167ffffffffffffffff80821115611888578384fd5b9084019060a0828703121561189b578384fd5b6118a560a0611f95565b8251828111156118b3578586fd5b6118bf8882860161140f565b8252506020830151828111156118d3578586fd5b6118df8882860161115d565b6020830152506040830151828111156118f6578586fd5b6119028882860161115d565b604083015250606083015182811115611919578586fd5b61192588828601611314565b60608301525060808301518281111561193c578586fd5b61194888828601611201565b608083015250935061195f915050602084016110dd565b90509250929050565b6000815180845260208085019450808401835b838110156119a05781516001600160a01b03168752958201959082019060010161197b565b509495945050505050565b6000815180845260208085018081965082840281019150828601855b85811015611a30578284038952815180518086529086019086860190878102870188018a5b82811015611a1a57601f19898303018452611a08828651611ada565b948a0194938a019391506001016119ec565b509b88019b9650505091850191506001016119c7565b5091979650505050505050565b6000815180845260208085018081965082840281019150828601855b85811015611a30578284038952815180518086529086019086860190895b81811015611a9657835160ff1683529288019291880191600101611a77565b50509986019994505090840190600101611a59565b6000815180845260208085019450808401835b838110156119a057815187529582019590820190600101611abe565b60008151808452611af2816020860160208601611ff9565b601f01601f19169290920160200192915050565b60008251611b18818460208701611ff9565b9190910192915050565b6001600160a01b0391909116815260200190565b60006001600160a01b0384168252604060208301526107396040830184611ada565b60006001600160a01b03808616835280851660208401525060806040830152600a60808301527f464c42616c616e6365720000000000000000000000000000000000000000000060a083015260c06060830152611bb860c0830184611ada565b95945050505050565b60006001600160a01b038616825260806020830152611be36080830186611968565b8281036040840152611bf58186611aab565b90508281036060840152611c098185611ada565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b90815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b600060208252610e376020830184611ada565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526014908201527f6d73672e73656e646572206e6f74206f776e6572000000000000000000000000604082015260600190565b60208082526010908201527f556e74727573746564206c656e64657200000000000000000000000000000000604082015260600190565b60208082526014908201527f6d73672e73656e646572206e6f742061646d696e000000000000000000000000604082015260600190565b60208082526014908201527f57726f6e67207061796261636b20616d6f756e74000000000000000000000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208252825160806020840152611e7060a0840182611968565b90506020840151601f1980858403016040860152611e8e8383611aab565b92506001600160a01b036040870151166060860152606086015191508085840301608086015250611bb88282611ada565b600060408252835160a06040840152611edb60e0840182611ada565b9050602080860151603f1980868503016060870152611efa84836119ab565b93506040880151915080868503016080870152611f1784836119ab565b6060890151878203830160a089015280518083529085019550869350908401905b80841015611f585785518252948401946001939093019290840190611f38565b5060808901519450818782030160c0880152611f748186611a3d565b9550505050848185015250509392505050565b60ff91909116815260200190565b60405181810167ffffffffffffffff81118282101715611fb157fe5b604052919050565b600067ffffffffffffffff821115611fcd57fe5b5060209081020190565b600067ffffffffffffffff821115611feb57fe5b50601f01601f191660200190565b60005b83811015612014578181015183820152602001611ffc565b83811115612023576000848401525b50505050565b6001600160a01b03811681146103d957600080fd5b60ff811681146103d957600080fdfe4164647265737320746f20776869636820746f6b656e732077696c6c2062652073656e7420746f2063616e2774206265206275726e2061646472657373a2646970667358221220dc0d57af7bcbf21b199502f46c9e9c1a33599febc23524eb21d14ebe3fe160b364736f6c63430007060033
Deployed Bytecode
0x60806040526004361061016a5760003560e01c80639864dcdd116100cb578063e910afb21161007f578063f829822d11610059578063f829822d1461035f578063f8e2fb0014610374578063fbfa77cf146103895761016a565b8063e910afb214610308578063f04f27071461032a578063f24ccbfe1461034a5761016a565b8063c579d490116100b0578063c579d490146102c0578063ca5ff780146102e0578063d3c2e7ed146102f35761016a565b80639864dcdd146102895780639ce3e9191461029e5761016a565b806341c0e1b5116101225780638237e538116101075780638237e5381461023d5780638bcb62161461025f5780638cedca71146102745761016a565b806341c0e1b5146102065780637b1039991461021b5761016a565b80631afd15be116101535780631afd15be146101c7578063247492f8146101dc5780632fa13cb8146101f15761016a565b80630336fd901461016f5780630f2eee42146101a5575b600080fd5b34801561017b57600080fd5b5061018f61018a366004611639565b61039e565b60405161019c9190611e54565b60405180910390f35b3480156101b157600080fd5b506101ba6103d4565b60405161019c9190611f87565b6101da6101d5366004611639565b6103d9565b005b3480156101e857600080fd5b506101ba6103dc565b3480156101fd57600080fd5b506101ba6103e1565b34801561021257600080fd5b506101da6103e6565b34801561022757600080fd5b506102306104a7565b60405161019c9190611b22565b34801561024957600080fd5b506102526104bf565b60405161019c9190611c2d565b34801561026b57600080fd5b506101ba6104e3565b34801561028057600080fd5b506102306104e8565b34801561029557600080fd5b506101ba610500565b3480156102aa57600080fd5b506102b3610505565b60405161019c9190611c36565b3480156102cc57600080fd5b506101da6102db36600461146e565b610529565b6102526102ee36600461166c565b610658565b3480156102ff57600080fd5b506101ba610741565b34801561031457600080fd5b5061031d610746565b60405161019c9190611c63565b34801561033657600080fd5b506101da610345366004611532565b61077f565b34801561035657600080fd5b50610230610afe565b34801561036b57600080fd5b5061031d610b16565b34801561038057600080fd5b5061031d610b32565b34801561039557600080fd5b50610230610b6b565b6103a66110ac565b816000815181106103b357fe5b60200260200101518060200190518101906103ce919061179d565b92915050565b608081565b50565b600090565b600081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561043d57600080fd5b505afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104759190611452565b6001600160a01b0316146104a45760405162461bcd60e51b815260040161049b90611d1b565b60405180910390fd5b33ff5b73d6049e1f5f3eff1f921f5532af1a1632ba23929c81565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b600181565b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b607f81565b7fd6741b9e0000000000000000000000000000000000000000000000000000000081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561058057600080fd5b505afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190611452565b6001600160a01b0316146105de5760405162461bcd60e51b815260040161049b90611cad565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038416141561063f576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610639573d6000803e3d6000fd5b50610653565b6106536001600160a01b0384168383610b83565b505050565b6000806106648661039e565b60408101519091506001600160a01b03161561070b5780604001516001600160a01b0316630ae1cc8e82606001516040518263ffffffff1660e01b81526004016106ae9190611c63565b60006040518083038186803b1580156106c657600080fd5b505afa1580156106da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261070291908101906114ae565b50602083015281525b60008660018851038151811061071d57fe5b6020026020010151905060006107338383610c06565b93505050505b949350505050565b60ff81565b6040518060400160405280601881526020017f57726f6e672072657475726e20696e6465782076616c7565000000000000000081525081565b600260005414156107a25760405162461bcd60e51b815260040161049b90611e1d565b60026000553373ba12222222228d8ba445958a75a0704d566bf2c8146107da5760405162461bcd60e51b815260040161049b90611ce4565b600080828060200190518101906107f1919061185f565b9150915060005b865181101561084e576108458287838151811061081157fe5b602002602001015189848151811061082557fe5b60200260200101516001600160a01b0316610d4c9092919063ffffffff16565b506001016107f8565b506040517f4ccee9b600000000000000000000000000000000000000000000000000000000815260009073d6049e1f5f3eff1f921f5532af1a1632ba23929c90634ccee9b6906108c2907fcec38b05fe06a488e2de01744d7ff3b8ac89eb607661ed3d7a4b16544d0c7a7290600401611c2d565b60206040518083038186803b1580156108da57600080fd5b505afa1580156108ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109129190611452565b9050816001600160a01b0316631cff79cd478363d6741b9e60e01b876109698b60008151811061093e57fe5b60200260200101518d60008151811061095357fe5b6020026020010151610e1290919063ffffffff16565b60405160240161097a929190611ebf565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526109ed9291600401611b36565b6020604051808303818588803b158015610a0657600080fd5b505af1158015610a1a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a3f9190611785565b5060005b8751811015610aef576000610a71878381518110610a5d57fe5b602002602001015189848151811061095357fe5b905080610aa3308b8581518110610a8457fe5b60200260200101516001600160a01b0316610e3e90919063ffffffff16565b14610ac05760405162461bcd60e51b815260040161049b90611d52565b610ae573ba12222222228d8ba445958a75a0704d566bf2c8828b858151811061082557fe5b5050600101610a43565b50506001600055505050505050565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6040518060600160405280603d815260200161204e603d913981565b6040518060400160405280601581526020017f57726f6e672073756220696e6465782076616c7565000000000000000000000081525081565b73ba12222222228d8ba445958a75a0704d566bf2c881565b6106538363a9059cbb60e01b8484604051602401610ba2929190611c14565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610f12565b815160208301516040517f5c38449e00000000000000000000000000000000000000000000000000000000815260009273ba12222222228d8ba445958a75a0704d566bf2c892635c38449e92610c6492309290918890600401611bc1565b600060405180830381600087803b158015610c7e57600080fd5b505af1158015610c92573d6000803e3d6000fd5b50505050735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce50303386604051602001610ccc9190611e54565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610cf993929190611b58565b600060405180830381600087803b158015610d1357600080fd5b505af1158015610d27573d6000803e3d6000fd5b505050508260200151600081518110610d3c57fe5b6020026020010151905092915050565b6000600019821415610d6557610d628430610e3e565b91505b6001600160a01b03831615801590610d8657506001600160a01b0383163014155b8015610d9157508115155b15610e0b576001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610dd357610dce6001600160a01b0385168484610b83565b610e0b565b6040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015610e09573d6000803e3d6000fd5b505b5092915050565b600082820183811015610e375760405162461bcd60e51b815260040161049b90611c76565b9392505050565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610e7657506001600160a01b038116316103ce565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038416906370a0823190610ebb908590600401611b22565b60206040518083038186803b158015610ed357600080fd5b505afa158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0b9190611785565b90506103ce565b6000610f67826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610fa19092919063ffffffff16565b8051909150156106535780806020019051810190610f859190611765565b6106535760405162461bcd60e51b815260040161049b90611dc0565b606061073984846000856060610fb68561106e565b610fd25760405162461bcd60e51b815260040161049b90611d89565b600080866001600160a01b03168587604051610fee9190611b06565b60006040518083038185875af1925050503d806000811461102b576040519150601f19603f3d011682016040523d82523d6000602084013e611030565b606091505b509150915081156110445791506107399050565b8051156110545780518082602001fd5b8360405162461bcd60e51b815260040161049b9190611c63565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906110a257508115155b925050505b919050565b6040518060800160405280606081526020016060815260200160006001600160a01b03168152602001606081525090565b80516110a781612029565b600082601f8301126110f8578081fd5b8151602061110d61110883611fb9565b611f95565b8281528181019085830183850287018401881015611129578586fd5b855b8581101561115057815161113e81612029565b8452928401929084019060010161112b565b5090979650505050505050565b600082601f83011261116d578081fd5b8151602061117d61110883611fb9565b82815281810190858301855b85811015611150578151880189603f8201126111a3578788fd5b858101516111b361110882611fb9565b81815287810190604084018b5b848110156111ea576111d88f6040845189010161140f565b8452928a0192908a01906001016111c0565b505087525050509284019290840190600101611189565b600082601f830112611211578081fd5b8151602061122161110883611fb9565b82815281810190858301855b85811015611150578151880189603f820112611247578788fd5b85810151604061125961110883611fb9565b828152888101908483018a8502860184018f1015611275578c8dfd5b8c95505b848610156112a3578051935061128e8461203e565b83835260019590950194918a01918a01611279565b50885250505093850193509084019060010161122d565b600082601f8301126112ca578081fd5b813560206112da61110883611fb9565b82815281810190858301838502870184018810156112f6578586fd5b855b85811015611150578135845292840192908401906001016112f8565b600082601f830112611324578081fd5b8151602061133461110883611fb9565b8281528181019085830183850287018401881015611350578586fd5b855b8581101561115057815184529284019290840190600101611352565b600082601f83011261137e578081fd5b8135602061138e61110883611fb9565b82815281810190858301855b85811015611150576113b1898684358b01016113c3565b8452928401929084019060010161139a565b600082601f8301126113d3578081fd5b81356113e161110882611fd7565b8181528460208386010111156113f5578283fd5b816020850160208301379081016020019190915292915050565b600082601f83011261141f578081fd5b815161142d61110882611fd7565b818152846020838601011115611441578283fd5b610739826020830160208701611ff9565b600060208284031215611463578081fd5b8151610e3781612029565b600080600060608486031215611482578182fd5b833561148d81612029565b9250602084013561149d81612029565b929592945050506040919091013590565b6000806000606084860312156114c2578081fd5b835167ffffffffffffffff808211156114d9578283fd5b6114e5878388016110e8565b945060208601519150808211156114fa578283fd5b61150687838801611314565b9350604086015191508082111561151b578283fd5b5061152886828701611314565b9150509250925092565b60008060008060808587031215611547578182fd5b843567ffffffffffffffff8082111561155e578384fd5b818701915087601f830112611571578384fd5b8135602061158161110883611fb9565b82815281810190858301838502870184018d101561159d578889fd5b8896505b848710156115c85780356115b481612029565b8352600196909601959183019183016115a1565b50985050880135925050808211156115de578384fd5b6115ea888389016112ba565b945060408701359150808211156115ff578384fd5b61160b888389016112ba565b93506060870135915080821115611620578283fd5b5061162d878288016113c3565b91505092959194509250565b60006020828403121561164a578081fd5b813567ffffffffffffffff811115611660578182fd5b6107398482850161136e565b60008060008060808587031215611681578182fd5b843567ffffffffffffffff80821115611698578384fd5b6116a48883890161136e565b95506020915081870135818111156116ba578485fd5b6116c689828a0161136e565b9550506040870135818111156116da578485fd5b8701601f810189136116ea578485fd5b80356116f861110882611fb9565b81815284810190838601868402850187018d1015611714578889fd5b8894505b8385101561173f57803561172b8161203e565b835260019490940193918601918601611718565b5096505050506060870135915080821115611758578283fd5b5061162d878288016112ba565b600060208284031215611776578081fd5b81518015158114610e37578182fd5b600060208284031215611796578081fd5b5051919050565b6000602082840312156117ae578081fd5b815167ffffffffffffffff808211156117c5578283fd5b90830190608082860312156117d8578283fd5b6117e26080611f95565b8251828111156117f0578485fd5b6117fc878286016110e8565b825250602083015182811115611810578485fd5b61181c87828601611314565b60208301525061182e604084016110dd565b6040820152606083015182811115611844578485fd5b6118508782860161140f565b60608301525095945050505050565b60008060408385031215611871578182fd5b825167ffffffffffffffff80821115611888578384fd5b9084019060a0828703121561189b578384fd5b6118a560a0611f95565b8251828111156118b3578586fd5b6118bf8882860161140f565b8252506020830151828111156118d3578586fd5b6118df8882860161115d565b6020830152506040830151828111156118f6578586fd5b6119028882860161115d565b604083015250606083015182811115611919578586fd5b61192588828601611314565b60608301525060808301518281111561193c578586fd5b61194888828601611201565b608083015250935061195f915050602084016110dd565b90509250929050565b6000815180845260208085019450808401835b838110156119a05781516001600160a01b03168752958201959082019060010161197b565b509495945050505050565b6000815180845260208085018081965082840281019150828601855b85811015611a30578284038952815180518086529086019086860190878102870188018a5b82811015611a1a57601f19898303018452611a08828651611ada565b948a0194938a019391506001016119ec565b509b88019b9650505091850191506001016119c7565b5091979650505050505050565b6000815180845260208085018081965082840281019150828601855b85811015611a30578284038952815180518086529086019086860190895b81811015611a9657835160ff1683529288019291880191600101611a77565b50509986019994505090840190600101611a59565b6000815180845260208085019450808401835b838110156119a057815187529582019590820190600101611abe565b60008151808452611af2816020860160208601611ff9565b601f01601f19169290920160200192915050565b60008251611b18818460208701611ff9565b9190910192915050565b6001600160a01b0391909116815260200190565b60006001600160a01b0384168252604060208301526107396040830184611ada565b60006001600160a01b03808616835280851660208401525060806040830152600a60808301527f464c42616c616e6365720000000000000000000000000000000000000000000060a083015260c06060830152611bb860c0830184611ada565b95945050505050565b60006001600160a01b038616825260806020830152611be36080830186611968565b8281036040840152611bf58186611aab565b90508281036060840152611c098185611ada565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b90815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b600060208252610e376020830184611ada565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526014908201527f6d73672e73656e646572206e6f74206f776e6572000000000000000000000000604082015260600190565b60208082526010908201527f556e74727573746564206c656e64657200000000000000000000000000000000604082015260600190565b60208082526014908201527f6d73672e73656e646572206e6f742061646d696e000000000000000000000000604082015260600190565b60208082526014908201527f57726f6e67207061796261636b20616d6f756e74000000000000000000000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208252825160806020840152611e7060a0840182611968565b90506020840151601f1980858403016040860152611e8e8383611aab565b92506001600160a01b036040870151166060860152606086015191508085840301608086015250611bb88282611ada565b600060408252835160a06040840152611edb60e0840182611ada565b9050602080860151603f1980868503016060870152611efa84836119ab565b93506040880151915080868503016080870152611f1784836119ab565b6060890151878203830160a089015280518083529085019550869350908401905b80841015611f585785518252948401946001939093019290840190611f38565b5060808901519450818782030160c0880152611f748186611a3d565b9550505050848185015250509392505050565b60ff91909116815260200190565b60405181810167ffffffffffffffff81118282101715611fb157fe5b604052919050565b600067ffffffffffffffff821115611fcd57fe5b5060209081020190565b600067ffffffffffffffff821115611feb57fe5b50601f01601f191660200190565b60005b83811015612014578181015183820152602001611ffc565b83811115612023576000848401525b50505050565b6001600160a01b03811681146103d957600080fd5b60ff811681146103d957600080fdfe4164647265737320746f20776869636820746f6b656e732077696c6c2062652073656e7420746f2063616e2774206265206275726e2061646472657373a2646970667358221220dc0d57af7bcbf21b199502f46c9e9c1a33599febc23524eb21d14ebe3fe160b364736f6c63430007060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.