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
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60c06040 | 16741565 | 628 days ago | IN | 0 ETH | 0.04908132 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
MorphoAaveV2SubProxy
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-03-02 */ // 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); } 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"); } } } abstract contract IDFSRegistry { function getAddr(bytes4 _id) public view virtual returns (address); function addNewContract( bytes32 _id, address _contractAddr, uint256 _waitPeriod ) public virtual; function startContractChange(bytes32 _id, address _newContractAddr) public virtual; function approveContractChange(bytes32 _id) public virtual; function cancelContractChange(bytes32 _id) public virtual; function changeWaitPeriod(bytes32 _id, uint256 _newWaitPeriod) public virtual; } contract MainnetAuthAddresses { address internal constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD; address internal constant FACTORY_ADDRESS = 0x5a15566417e6C1c9546523066500bDDBc53F88C7; address internal constant ADMIN_ADDR = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9; // USED IN ADMIN VAULT CONSTRUCTOR } contract AuthHelper is MainnetAuthAddresses { } contract AdminVault is AuthHelper { address public owner; address public admin; error SenderNotAdmin(); constructor() { owner = msg.sender; admin = ADMIN_ADDR; } /// @notice Admin is able to change owner /// @param _owner Address of new owner function changeOwner(address _owner) public { if (admin != msg.sender){ revert SenderNotAdmin(); } owner = _owner; } /// @notice Admin is able to set new admin /// @param _admin Address of multisig that becomes new admin function changeAdmin(address _admin) public { if (admin != msg.sender){ revert SenderNotAdmin(); } admin = _admin; } } contract AdminAuth is AuthHelper { using SafeERC20 for IERC20; AdminVault public constant adminVault = AdminVault(ADMIN_VAULT_ADDR); error SenderNotOwner(); error SenderNotAdmin(); modifier onlyOwner() { if (adminVault.owner() != msg.sender){ revert SenderNotOwner(); } _; } modifier onlyAdmin() { if (adminVault.admin() != msg.sender){ revert SenderNotAdmin(); } _; } /// @notice withdraw stuck funds function withdrawStuckFunds(address _token, address _receiver, uint256 _amount) public onlyOwner { if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { payable(_receiver).transfer(_amount); } else { IERC20(_token).safeTransfer(_receiver, _amount); } } /// @notice Destroy the contract function kill() public onlyAdmin { selfdestruct(payable(msg.sender)); } } abstract contract DSGuard { function canCall( address src_, address dst_, bytes4 sig ) public view virtual returns (bool); function permit( bytes32 src, bytes32 dst, bytes32 sig ) public virtual; function forbid( bytes32 src, bytes32 dst, bytes32 sig ) public virtual; function permit( address src, address dst, bytes32 sig ) public virtual; function forbid( address src, address dst, bytes32 sig ) public virtual; } abstract contract DSGuardFactory { function newGuard() public virtual returns (DSGuard guard); } 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 ProxyPermission is AuthHelper { bytes4 public constant EXECUTE_SELECTOR = bytes4(keccak256("execute(address,bytes)")); /// @notice Called in the context of DSProxy to authorize an address /// @param _contractAddr Address which will be authorized function givePermission(address _contractAddr) public { address currAuthority = address(DSAuth(address(this)).authority()); DSGuard guard = DSGuard(currAuthority); if (currAuthority == address(0)) { guard = DSGuardFactory(FACTORY_ADDRESS).newGuard(); DSAuth(address(this)).setAuthority(DSAuthority(address(guard))); } if (!guard.canCall(_contractAddr, address(this), EXECUTE_SELECTOR)) { guard.permit(_contractAddr, address(this), EXECUTE_SELECTOR); } } /// @notice Called in the context of DSProxy to remove authority of an address /// @param _contractAddr Auth address which will be removed from authority list function removePermission(address _contractAddr) public { address currAuthority = address(DSAuth(address(this)).authority()); // if there is no authority, that means that contract doesn't have permission if (currAuthority == address(0)) { return; } DSGuard guard = DSGuard(currAuthority); guard.forbid(_contractAddr, address(this), EXECUTE_SELECTOR); } } 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); } } contract StrategyModel { /// @dev Group of strategies bundled together so user can sub to multiple strategies at once /// @param creator Address of the user who created the bundle /// @param strategyIds Array of strategy ids stored in StrategyStorage struct StrategyBundle { address creator; uint64[] strategyIds; } /// @dev Template/Class which defines a Strategy /// @param name Name of the strategy useful for logging what strategy is executing /// @param creator Address of the user which created the strategy /// @param triggerIds Array of identifiers for trigger - bytes4(keccak256(TriggerName)) /// @param actionIds Array of identifiers for actions - bytes4(keccak256(ActionName)) /// @param paramMapping Describes how inputs to functions are piped from return/subbed values /// @param continuous If the action is repeated (continuos) or one time struct Strategy { string name; address creator; bytes4[] triggerIds; bytes4[] actionIds; uint8[][] paramMapping; bool continuous; } /// @dev List of actions grouped as a recipe /// @param name Name of the recipe useful for logging what recipe is executing /// @param callData Array of calldata inputs to each action /// @param subData Used only as part of strategy, subData injected from StrategySub.subData /// @param actionIds Array of identifiers for actions - bytes4(keccak256(ActionName)) /// @param paramMapping Describes how inputs to functions are piped from return/subbed values struct Recipe { string name; bytes[] callData; bytes32[] subData; bytes4[] actionIds; uint8[][] paramMapping; } /// @dev Actual data of the sub we store on-chain /// @dev In order to save on gas we store a keccak256(StrategySub) and verify later on /// @param userProxy Address of the users smart wallet/proxy /// @param isEnabled Toggle if the subscription is active /// @param strategySubHash Hash of the StrategySub data the user inputted struct StoredSubData { bytes20 userProxy; // address but put in bytes20 for gas savings bool isEnabled; bytes32 strategySubHash; } /// @dev Instance of a strategy, user supplied data /// @param strategyOrBundleId Id of the strategy or bundle, depending on the isBundle bool /// @param isBundle If true the id points to bundle, if false points directly to strategyId /// @param triggerData User supplied data needed for checking trigger conditions /// @param subData User supplied data used in recipe struct StrategySub { uint64 strategyOrBundleId; bool isBundle; bytes[] triggerData; bytes32[] subData; } } contract StrategyStorage is StrategyModel, AdminAuth { Strategy[] public strategies; bool public openToPublic = false; error NoAuthToCreateStrategy(address,bool); event StrategyCreated(uint256 indexed strategyId); modifier onlyAuthCreators { if (adminVault.owner() != msg.sender && openToPublic == false) { revert NoAuthToCreateStrategy(msg.sender, openToPublic); } _; } /// @notice Creates a new strategy and writes the data in an array /// @dev Can only be called by auth addresses if it's not open to public /// @param _name Name of the strategy useful for logging what strategy is executing /// @param _triggerIds Array of identifiers for trigger - bytes4(keccak256(TriggerName)) /// @param _actionIds Array of identifiers for actions - bytes4(keccak256(ActionName)) /// @param _paramMapping Describes how inputs to functions are piped from return/subbed values /// @param _continuous If the action is repeated (continuos) or one time function createStrategy( string memory _name, bytes4[] memory _triggerIds, bytes4[] memory _actionIds, uint8[][] memory _paramMapping, bool _continuous ) public onlyAuthCreators returns (uint256) { strategies.push(Strategy({ name: _name, creator: msg.sender, triggerIds: _triggerIds, actionIds: _actionIds, paramMapping: _paramMapping, continuous : _continuous })); emit StrategyCreated(strategies.length - 1); return strategies.length - 1; } /// @notice Switch to determine if bundles can be created by anyone /// @dev Callable only by the owner /// @param _openToPublic Flag if true anyone can create bundles function changeEditPermission(bool _openToPublic) public onlyOwner { openToPublic = _openToPublic; } ////////////////////////////// VIEW METHODS ///////////////////////////////// function getStrategy(uint _strategyId) public view returns (Strategy memory) { return strategies[_strategyId]; } function getStrategyCount() public view returns (uint256) { return strategies.length; } function getPaginatedStrategies(uint _page, uint _perPage) public view returns (Strategy[] memory) { Strategy[] memory strategiesPerPage = new Strategy[](_perPage); uint start = _page * _perPage; uint end = start + _perPage; end = (end > strategies.length) ? strategies.length : end; uint count = 0; for (uint i = start; i < end; i++) { strategiesPerPage[count] = strategies[i]; count++; } return strategiesPerPage; } } contract MainnetCoreAddresses { address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b; address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70; address internal constant DEFISAVER_LOGGER = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3; address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90; address internal constant BUNDLE_STORAGE_ADDR = 0x223c6aDE533851Df03219f6E3D8B763Bd47f84cf; address internal constant STRATEGY_STORAGE_ADDR = 0xF52551F95ec4A2B4299DcC42fbbc576718Dbf933; address constant internal RECIPE_EXECUTOR_ADDR = 0x1D6DEdb49AF91A11B5C5F34954FD3E8cC4f03A86; } contract CoreHelper is MainnetCoreAddresses { } contract BundleStorage is StrategyModel, AdminAuth, CoreHelper { DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR); StrategyBundle[] public bundles; bool public openToPublic = false; error NoAuthToCreateBundle(address,bool); error DiffTriggersInBundle(uint64[]); event BundleCreated(uint256 indexed bundleId); modifier onlyAuthCreators { if (adminVault.owner() != msg.sender && openToPublic == false) { revert NoAuthToCreateBundle(msg.sender, openToPublic); } _; } /// @dev Checks if the triggers in strategies are the same (order also relevant) /// @dev If the caller is not owner we do additional checks, we skip those checks for gas savings modifier sameTriggers(uint64[] memory _strategyIds) { if (msg.sender != adminVault.owner()) { Strategy memory firstStrategy = StrategyStorage(STRATEGY_STORAGE_ADDR).getStrategy(_strategyIds[0]); bytes32 firstStrategyTriggerHash = keccak256(abi.encode(firstStrategy.triggerIds)); for (uint256 i = 1; i < _strategyIds.length; ++i) { Strategy memory s = StrategyStorage(STRATEGY_STORAGE_ADDR).getStrategy(_strategyIds[i]); if (firstStrategyTriggerHash != keccak256(abi.encode(s.triggerIds))) { revert DiffTriggersInBundle(_strategyIds); } } } _; } /// @notice Adds a new bundle to array /// @dev Can only be called by auth addresses if it's not open to public /// @dev Strategies need to have the same number of triggers and ids exists /// @param _strategyIds Array of strategyIds that go into a bundle function createBundle( uint64[] memory _strategyIds ) public onlyAuthCreators sameTriggers(_strategyIds) returns (uint256) { bundles.push(StrategyBundle({ creator: msg.sender, strategyIds: _strategyIds })); emit BundleCreated(bundles.length - 1); return bundles.length - 1; } /// @notice Switch to determine if bundles can be created by anyone /// @dev Callable only by the owner /// @param _openToPublic Flag if true anyone can create bundles function changeEditPermission(bool _openToPublic) public onlyOwner { openToPublic = _openToPublic; } ////////////////////////////// VIEW METHODS ///////////////////////////////// function getStrategyId(uint256 _bundleId, uint256 _strategyIndex) public view returns (uint256) { return bundles[_bundleId].strategyIds[_strategyIndex]; } function getBundle(uint _bundleId) public view returns (StrategyBundle memory) { return bundles[_bundleId]; } function getBundleCount() public view returns (uint256) { return bundles.length; } function getPaginatedBundles(uint _page, uint _perPage) public view returns (StrategyBundle[] memory) { StrategyBundle[] memory bundlesPerPage = new StrategyBundle[](_perPage); uint start = _page * _perPage; uint end = start + _perPage; end = (end > bundles.length) ? bundles.length : end; uint count = 0; for (uint i = start; i < end; i++) { bundlesPerPage[count] = bundles[i]; count++; } return bundlesPerPage; } } contract SubStorage is StrategyModel, AdminAuth, CoreHelper { error SenderNotSubOwnerError(address, uint256); error SubIdOutOfRange(uint256, bool); event Subscribe(uint256 indexed subId, address indexed proxy, bytes32 indexed subHash, StrategySub subStruct); event UpdateData(uint256 indexed subId, bytes32 indexed subHash, StrategySub subStruct); event ActivateSub(uint256 indexed subId); event DeactivateSub(uint256 indexed subId); DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR); StoredSubData[] public strategiesSubs; /// @notice Checks if subId is init. and if the sender is the owner modifier onlySubOwner(uint256 _subId) { if (address(strategiesSubs[_subId].userProxy) != msg.sender) { revert SenderNotSubOwnerError(msg.sender, _subId); } _; } /// @notice Checks if the id is valid (points to a stored bundle/sub) modifier isValidId(uint256 _id, bool _isBundle) { if (_isBundle) { if (_id > (BundleStorage(BUNDLE_STORAGE_ADDR).getBundleCount() - 1)) { revert SubIdOutOfRange(_id, _isBundle); } } else { if (_id > (StrategyStorage(STRATEGY_STORAGE_ADDR).getStrategyCount() - 1)) { revert SubIdOutOfRange(_id, _isBundle); } } _; } /// @notice Adds users info and records StoredSubData, logs StrategySub /// @dev To save on gas we don't store the whole struct but rather the hash of the struct /// @param _sub Subscription struct of the user (is not stored on chain, only the hash) function subscribeToStrategy( StrategySub memory _sub ) public isValidId(_sub.strategyOrBundleId, _sub.isBundle) returns (uint256) { bytes32 subStorageHash = keccak256(abi.encode(_sub)); strategiesSubs.push(StoredSubData( bytes20(msg.sender), true, subStorageHash )); uint256 currentId = strategiesSubs.length - 1; emit Subscribe(currentId, msg.sender, subStorageHash, _sub); return currentId; } /// @notice Updates the users subscription data /// @dev Only callable by proxy who created the sub. /// @param _subId Id of the subscription to update /// @param _sub Subscription struct of the user (needs whole struct so we can hash it) function updateSubData( uint256 _subId, StrategySub calldata _sub ) public onlySubOwner(_subId) isValidId(_sub.strategyOrBundleId, _sub.isBundle) { StoredSubData storage storedSubData = strategiesSubs[_subId]; bytes32 subStorageHash = keccak256(abi.encode(_sub)); storedSubData.strategySubHash = subStorageHash; emit UpdateData(_subId, subStorageHash, _sub); } /// @notice Enables the subscription for execution if disabled /// @dev Must own the sub. to be able to enable it /// @param _subId Id of subscription to enable function activateSub( uint _subId ) public onlySubOwner(_subId) { StoredSubData storage sub = strategiesSubs[_subId]; sub.isEnabled = true; emit ActivateSub(_subId); } /// @notice Disables the subscription (will not be able to execute the strategy for the user) /// @dev Must own the sub. to be able to disable it /// @param _subId Id of subscription to disable function deactivateSub( uint _subId ) public onlySubOwner(_subId) { StoredSubData storage sub = strategiesSubs[_subId]; sub.isEnabled = false; emit DeactivateSub(_subId); } ///////////////////// VIEW ONLY FUNCTIONS //////////////////////////// function getSub(uint _subId) public view returns (StoredSubData memory) { return strategiesSubs[_subId]; } function getSubsCount() public view returns (uint256) { return strategiesSubs.length; } } contract MorphoAaveV2SubProxy is StrategyModel, AdminAuth, ProxyPermission, CoreHelper { uint64 public immutable REPAY_BUNDLE_ID; uint64 public immutable BOOST_BUNDLE_ID; constructor(uint64 _repayBundleId, uint64 _boostBundleId) { REPAY_BUNDLE_ID = _repayBundleId; BOOST_BUNDLE_ID = _boostBundleId; } enum RatioState { OVER, UNDER } /// @dev 5% offset acceptable uint256 internal constant RATIO_OFFSET = 50000000000000000; error WrongSubParams(uint256 minRatio, uint256 maxRatio); error RangeTooClose(uint256 ratio, uint256 targetRatio); struct MorphoAaveV2SubData { uint128 minRatio; uint128 maxRatio; uint128 targetRatioBoost; uint128 targetRatioRepay; bool boostEnabled; } /// @notice Parses input data and subscribes user to repay and boost bundles /// @dev Gives DSProxy permission if needed and registers a new sub /// @dev If boostEnabled = false it will only create a repay bundle /// @dev User can't just sub a boost bundle without repay function subToMorphoAaveV2Automation( MorphoAaveV2SubData calldata _subData ) public { givePermission(PROXY_AUTH_ADDR); StrategySub memory repaySub = formatRepaySub(_subData, address(this)); SubStorage(SUB_STORAGE_ADDR).subscribeToStrategy(repaySub); if (_subData.boostEnabled) { _validateSubData(_subData); StrategySub memory boostSub = formatBoostSub(_subData, address(this)); SubStorage(SUB_STORAGE_ADDR).subscribeToStrategy(boostSub); } } /// @notice Calls SubStorage to update the users subscription data /// @dev Updating sub data will activate it as well /// @dev If we don't have a boost subId send as 0 function updateSubData( uint32 _subId1, uint32 _subId2, MorphoAaveV2SubData calldata _subData ) public { // update repay as we must have a subId, it's ok if it's the same data StrategySub memory repaySub = formatRepaySub(_subData, address(this)); SubStorage(SUB_STORAGE_ADDR).updateSubData(_subId1, repaySub); SubStorage(SUB_STORAGE_ADDR).activateSub(_subId1); if (_subData.boostEnabled) { _validateSubData(_subData); StrategySub memory boostSub = formatBoostSub(_subData, address(this)); // if we don't have a boost bundleId, create one if (_subId2 == 0) { SubStorage(SUB_STORAGE_ADDR).subscribeToStrategy(boostSub); } else { SubStorage(SUB_STORAGE_ADDR).updateSubData(_subId2, boostSub); SubStorage(SUB_STORAGE_ADDR).activateSub(_subId2); } } else { if (_subId2 != 0) { SubStorage(SUB_STORAGE_ADDR).deactivateSub(_subId2); } } } /// @notice Activates Repay sub and if exists a Boost sub function activateSub( uint32 _subId1, uint32 _subId2 ) public { SubStorage(SUB_STORAGE_ADDR).activateSub(_subId1); if (_subId2 != 0) { SubStorage(SUB_STORAGE_ADDR).activateSub(_subId2); } } /// @notice Deactivates Repay sub and if exists a Boost sub function deactivateSub( uint32 _subId1, uint32 _subId2 ) public { SubStorage(SUB_STORAGE_ADDR).deactivateSub(_subId1); if (_subId2 != 0) { SubStorage(SUB_STORAGE_ADDR).deactivateSub(_subId2); } } ///////////////////////////////// HELPER FUNCTIONS ///////////////////////////////// function _validateSubData(MorphoAaveV2SubData memory _subData) internal pure { if (_subData.minRatio > _subData.maxRatio) { revert WrongSubParams(_subData.minRatio, _subData.maxRatio); } if ((_subData.maxRatio - RATIO_OFFSET) < _subData.targetRatioRepay) { revert RangeTooClose(_subData.maxRatio, _subData.targetRatioRepay); } if ((_subData.minRatio + RATIO_OFFSET) > _subData.targetRatioBoost) { revert RangeTooClose(_subData.minRatio, _subData.targetRatioBoost); } } /// @notice Formats a StrategySub struct to a Repay bundle from the input data of the specialized morphoAaveV2 sub function formatRepaySub(MorphoAaveV2SubData memory _subData, address _proxy) public view returns (StrategySub memory repaySub) { repaySub.strategyOrBundleId = REPAY_BUNDLE_ID; repaySub.isBundle = true; // format data for ratio trigger if currRatio < minRatio = true bytes memory triggerData = abi.encode(_proxy, uint256(_subData.minRatio), uint8(RatioState.UNDER)); repaySub.triggerData = new bytes[](1); repaySub.triggerData[0] = triggerData; repaySub.subData = new bytes32[](2); repaySub.subData[0] = bytes32(uint256(1)); // ratioState = repay repaySub.subData[1] = bytes32(uint256(_subData.targetRatioRepay)); // targetRatio } /// @notice Formats a StrategySub struct to a Boost bundle from the input data of the specialized morphoAaveV2 sub function formatBoostSub(MorphoAaveV2SubData memory _subData, address _proxy) public view returns (StrategySub memory boostSub) { boostSub.strategyOrBundleId = BOOST_BUNDLE_ID; boostSub.isBundle = true; // format data for ratio trigger if currRatio > maxRatio = true bytes memory triggerData = abi.encode(_proxy, uint256(_subData.maxRatio), uint8(RatioState.OVER)); boostSub.triggerData = new bytes[](1); boostSub.triggerData[0] = triggerData; boostSub.subData = new bytes32[](2); boostSub.subData[0] = bytes32(uint256(0)); // ratioState = boost boostSub.subData[1] = bytes32(uint256(_subData.targetRatioBoost)); // targetRatio } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint64","name":"_repayBundleId","type":"uint64"},{"internalType":"uint64","name":"_boostBundleId","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"uint256","name":"targetRatio","type":"uint256"}],"name":"RangeTooClose","type":"error"},{"inputs":[],"name":"SenderNotAdmin","type":"error"},{"inputs":[],"name":"SenderNotOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"WrongSubParams","type":"error"},{"inputs":[],"name":"BOOST_BUNDLE_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXECUTE_SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPAY_BUNDLE_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_subId1","type":"uint32"},{"internalType":"uint32","name":"_subId2","type":"uint32"}],"name":"activateSub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminVault","outputs":[{"internalType":"contract AdminVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_subId1","type":"uint32"},{"internalType":"uint32","name":"_subId2","type":"uint32"}],"name":"deactivateSub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"minRatio","type":"uint128"},{"internalType":"uint128","name":"maxRatio","type":"uint128"},{"internalType":"uint128","name":"targetRatioBoost","type":"uint128"},{"internalType":"uint128","name":"targetRatioRepay","type":"uint128"},{"internalType":"bool","name":"boostEnabled","type":"bool"}],"internalType":"struct MorphoAaveV2SubProxy.MorphoAaveV2SubData","name":"_subData","type":"tuple"},{"internalType":"address","name":"_proxy","type":"address"}],"name":"formatBoostSub","outputs":[{"components":[{"internalType":"uint64","name":"strategyOrBundleId","type":"uint64"},{"internalType":"bool","name":"isBundle","type":"bool"},{"internalType":"bytes[]","name":"triggerData","type":"bytes[]"},{"internalType":"bytes32[]","name":"subData","type":"bytes32[]"}],"internalType":"struct StrategyModel.StrategySub","name":"boostSub","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"minRatio","type":"uint128"},{"internalType":"uint128","name":"maxRatio","type":"uint128"},{"internalType":"uint128","name":"targetRatioBoost","type":"uint128"},{"internalType":"uint128","name":"targetRatioRepay","type":"uint128"},{"internalType":"bool","name":"boostEnabled","type":"bool"}],"internalType":"struct MorphoAaveV2SubProxy.MorphoAaveV2SubData","name":"_subData","type":"tuple"},{"internalType":"address","name":"_proxy","type":"address"}],"name":"formatRepaySub","outputs":[{"components":[{"internalType":"uint64","name":"strategyOrBundleId","type":"uint64"},{"internalType":"bool","name":"isBundle","type":"bool"},{"internalType":"bytes[]","name":"triggerData","type":"bytes[]"},{"internalType":"bytes32[]","name":"subData","type":"bytes32[]"}],"internalType":"struct StrategyModel.StrategySub","name":"repaySub","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddr","type":"address"}],"name":"givePermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddr","type":"address"}],"name":"removePermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"minRatio","type":"uint128"},{"internalType":"uint128","name":"maxRatio","type":"uint128"},{"internalType":"uint128","name":"targetRatioBoost","type":"uint128"},{"internalType":"uint128","name":"targetRatioRepay","type":"uint128"},{"internalType":"bool","name":"boostEnabled","type":"bool"}],"internalType":"struct MorphoAaveV2SubProxy.MorphoAaveV2SubData","name":"_subData","type":"tuple"}],"name":"subToMorphoAaveV2Automation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_subId1","type":"uint32"},{"internalType":"uint32","name":"_subId2","type":"uint32"},{"components":[{"internalType":"uint128","name":"minRatio","type":"uint128"},{"internalType":"uint128","name":"maxRatio","type":"uint128"},{"internalType":"uint128","name":"targetRatioBoost","type":"uint128"},{"internalType":"uint128","name":"targetRatioRepay","type":"uint128"},{"internalType":"bool","name":"boostEnabled","type":"bool"}],"internalType":"struct MorphoAaveV2SubProxy.MorphoAaveV2SubData","name":"_subData","type":"tuple"}],"name":"updateSubData","outputs":[],"stateMutability":"nonpayable","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
60c06040523480156200001157600080fd5b5060405162001e7d38038062001e7d833981016040819052620000349162000069565b6001600160401b039182166080521660a052620000a1565b80516001600160401b03811681146200006457600080fd5b919050565b600080604083850312156200007d57600080fd5b62000088836200004c565b915062000098602084016200004c565b90509250929050565b60805160a051611da8620000d5600039600081816102210152610ae001526000818161010901526107e80152611da86000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80639f6197b71161008c578063e074bb4711610066578063e074bb4714610269578063f0c56eed1461027c578063f20311f01461028f578063fd6bf387146102a257600080fd5b80639f6197b71461021c578063c579d49014610243578063cb8076391461025657600080fd5b806341c0e1b5116100c857806341c0e1b51461015c5780637210cf961461016457806385d63353146101845780638cedca71146101dc57600080fd5b80632fc044de146100ef578063369465a1146101045780633d391f7014610149575b600080fd5b6101026100fd366004611838565b6102b5565b005b61012b7f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61010261015736600461188d565b6103cf565b6101026106da565b61017761017236600461199a565b6107c4565b6040516101409190611b3f565b6101ab7f1cff79cde515a86f6cc1adbebe8ae25888905561371faf11c8102211f56b487081565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610140565b6101f773ccf3d848e08b94478ed8f46ffead3008faf581fd81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610140565b61012b7f000000000000000000000000000000000000000000000000000000000000000081565b610102610251366004611b52565b610939565b61017761026436600461199a565b610abc565b61010261027736600461188d565b610c1f565b61010261028a366004611bab565b610d34565b61010261029d366004611bef565b6110e8565b6101026102b0366004611838565b611281565b6040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace690602401600060405180830381600087803b15801561032057600080fd5b505af1158015610334573d6000803e3d6000fd5b505050508063ffffffff166000146103cb576040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace6906024015b600060405180830381600087803b1580156103b257600080fd5b505af11580156103c6573d6000803e3d6000fd5b505050505b5050565b60003073ffffffffffffffffffffffffffffffffffffffff1663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104409190611c0b565b90508073ffffffffffffffffffffffffffffffffffffffff811661056657735a15566417e6c1c9546523066500bddbc53f88c773ffffffffffffffffffffffffffffffffffffffff166365688cc96040518163ffffffff1660e01b81526004016020604051808303816000875af11580156104bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e39190611c0b565b6040517f7a9e5e4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091503090637a9e5e4b90602401600060405180830381600087803b15801561054d57600080fd5b505af1158015610561573d6000803e3d6000fd5b505050505b6040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301527f1cff79cd00000000000000000000000000000000000000000000000000000000604483015282169063b700961390606401602060405180830381865afa1580156105fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106229190611c28565b6106d5576040517fcbeea68c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301527f1cff79cd00000000000000000000000000000000000000000000000000000000604483015282169063cbeea68c906064015b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b505050505b505050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107749190611c0b565b73ffffffffffffffffffffffffffffffffffffffff16146107c1576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160808082018352606082840181905280830181905267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168352600160208085018290528751865173ffffffffffffffffffffffffffffffffffffffff8916928101929092526fffffffffffffffffffffffffffffffff16818701528083018290528551808203909301835292830181815260c0840190955292939092909160a0015b60608152602001906001900390816108735750506040830181905280518291906000906108a2576108a2611c45565b60209081029190910101526040805160028082526060820190925290816020016020820280368337505050606083018190528051600191906000906108e9576108e9611c45565b60200260200101818152505083606001516fffffffffffffffffffffffffffffffff1660001b826060015160018151811061092657610926611c45565b6020026020010181815250505092915050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190611c0b565b73ffffffffffffffffffffffffffffffffffffffff1614610a20576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610a9b5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610a95573d6000803e3d6000fd5b50505050565b6106d573ffffffffffffffffffffffffffffffffffffffff84168383611368565b6040805160808082018352606082840181905280830181905267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001683526001602080850182905287810151865173ffffffffffffffffffffffffffffffffffffffff8916928101929092526fffffffffffffffffffffffffffffffff16818701526000818401528551808203909301835292830181815260c0840190955292939092909160a0015b6060815260200190600190039081610b6d575050604083018190528051829190600090610b9c57610b9c611c45565b60209081029190910101526040805160028082526060820190925290816020016020820280368337505050606083018190528051600091908290610be257610be2611c45565b60200260200101818152505083604001516fffffffffffffffffffffffffffffffff1660001b826060015160018151811061092657610926611c45565b60003073ffffffffffffffffffffffffffffffffffffffff1663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c909190611c0b565b905073ffffffffffffffffffffffffffffffffffffffff8116610cb1575050565b6040517f2bc3217d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301523060248301527f1cff79cd000000000000000000000000000000000000000000000000000000006044830152829190821690632bc3217d906064016106a2565b6000610d4e610d4836849003840184611c74565b306107c4565b6040517ff14283c2000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e909063f14283c290610da39087908590600401611c90565b600060405180830381600087803b158015610dbd57600080fd5b505af1158015610dd1573d6000803e3d6000fd5b50506040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff87166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909250633fb387bd9150602401600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b50610e699250505060a0830160808401611caf565b1561105357610e85610e8036849003840184611c74565b6113f5565b6000610e9f610e9936859003850185611c74565b30610abc565b905063ffffffff8416610f45576040517f3ab9a078000000000000000000000000000000000000000000000000000000008152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a07890610efc908490600401611b3f565b6020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190611ccc565b5061104d565b6040517ff14283c2000000000000000000000000000000000000000000000000000000008152731612fc28ee0ab882ec99842cde0fc77ff0691e909063f14283c290610f979087908590600401611c90565b600060405180830381600087803b158015610fb157600080fd5b505af1158015610fc5573d6000803e3d6000fd5b50506040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff87166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909250633fb387bd9150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050505b50610a95565b63ffffffff831615610a95576040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace690602401600060405180830381600087803b1580156110ca57600080fd5b505af11580156110de573d6000803e3d6000fd5b5050505050505050565b61110573149667b6fae2c63d1b4317c716b0d0e4d3e2bd706103cf565b6000611119610d4836849003840184611c74565b6040517f3ab9a078000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a0789061116c908490600401611b3f565b6020604051808303816000875af115801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af9190611ccc565b506111c060a0830160808401611caf565b156103cb576111d7610e8036849003840184611c74565b60006111eb610e9936859003850185611c74565b6040517f3ab9a078000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a0789061123e908490600401611b3f565b6020604051808303816000875af115801561125d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611ccc565b6040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633fb387bd90602401600060405180830381600087803b1580156112ec57600080fd5b505af1158015611300573d6000803e3d6000fd5b505050508063ffffffff166000146103cb576040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633fb387bd90602401610398565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526106d59084906115bf565b80602001516fffffffffffffffffffffffffffffffff1681600001516fffffffffffffffffffffffffffffffff16111561148357805160208201516040517f866a0beb0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff9283166004820152911660248201526044015b60405180910390fd5b80606001516fffffffffffffffffffffffffffffffff1666b1a2bc2ec5000082602001516fffffffffffffffffffffffffffffffff166114c39190611d14565b101561152157602081015160608201516040517f25a5396b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff92831660048201529116602482015260440161147a565b80604001516fffffffffffffffffffffffffffffffff1666b1a2bc2ec5000082600001516fffffffffffffffffffffffffffffffff166115619190611d2b565b11156115bc57805160408083015190517f25a5396b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff92831660048201529116602482015260440161147a565b50565b6000611621826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166116cb9092919063ffffffff16565b8051909150156106d5578080602001905181019061163f9190611c28565b6106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161147a565b60606116da84846000856116e2565b949350505050565b60606116ed856117e6565b611723576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161174c9190611d43565b60006040518083038185875af1925050503d8060008114611789576040519150601f19603f3d011682016040523d82523d6000602084013e61178e565b606091505b509150915081156117a25791506116da9050565b8051156117b25780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147a9190611d5f565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906116da575050151592915050565b803563ffffffff8116811461183357600080fd5b919050565b6000806040838503121561184b57600080fd5b6118548361181f565b91506118626020840161181f565b90509250929050565b73ffffffffffffffffffffffffffffffffffffffff811681146115bc57600080fd5b60006020828403121561189f57600080fd5b81356118aa8161186b565b9392505050565b80356fffffffffffffffffffffffffffffffff8116811461183357600080fd5b80151581146115bc57600080fd5b600060a082840312156118f157600080fd5b60405160a0810181811067ffffffffffffffff8211171561193b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061194a836118b1565b8152611958602084016118b1565b6020820152611969604084016118b1565b604082015261197a606084016118b1565b6060820152608083013561198d816118d1565b6080919091015292915050565b60008060c083850312156119ad57600080fd5b6119b784846118df565b915060a08301356119c78161186b565b809150509250929050565b60005b838110156119ed5781810151838201526020016119d5565b83811115610a955750506000910152565b60008151808452611a168160208601602086016119d2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501945080840160005b83811015611a7857815187529582019590820190600101611a5c565b509495945050505050565b60006080830167ffffffffffffffff835116845260208084015115158186015260408401516080604087015282815180855260a08801915060a08160051b8901019450838301925060005b81811015611b1a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60898703018352611b088685516119fe565b95509284019291840191600101611ace565b505050505060608301518482036060860152611b368282611a48565b95945050505050565b6020815260006118aa6020830184611a83565b600080600060608486031215611b6757600080fd5b8335611b728161186b565b92506020840135611b828161186b565b929592945050506040919091013590565b600060a08284031215611ba557600080fd5b50919050565b600080600060e08486031215611bc057600080fd5b611bc98461181f565b9250611bd76020850161181f565b9150611be68560408601611b93565b90509250925092565b600060a08284031215611c0157600080fd5b6118aa8383611b93565b600060208284031215611c1d57600080fd5b81516118aa8161186b565b600060208284031215611c3a57600080fd5b81516118aa816118d1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611c8657600080fd5b6118aa83836118df565b63ffffffff831681526040602082015260006116da6040830184611a83565b600060208284031215611cc157600080fd5b81356118aa816118d1565b600060208284031215611cde57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611d2657611d26611ce5565b500390565b60008219821115611d3e57611d3e611ce5565b500190565b60008251611d558184602087016119d2565b9190910192915050565b6020815260006118aa60208301846119fe56fea2646970667358221220e90197807ac04e764cbd235cac1ab25c54b25aa1feec2ec9538c9b4866a6b5d064736f6c634300080a0033000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c80639f6197b71161008c578063e074bb4711610066578063e074bb4714610269578063f0c56eed1461027c578063f20311f01461028f578063fd6bf387146102a257600080fd5b80639f6197b71461021c578063c579d49014610243578063cb8076391461025657600080fd5b806341c0e1b5116100c857806341c0e1b51461015c5780637210cf961461016457806385d63353146101845780638cedca71146101dc57600080fd5b80632fc044de146100ef578063369465a1146101045780633d391f7014610149575b600080fd5b6101026100fd366004611838565b6102b5565b005b61012b7f000000000000000000000000000000000000000000000000000000000000000e81565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61010261015736600461188d565b6103cf565b6101026106da565b61017761017236600461199a565b6107c4565b6040516101409190611b3f565b6101ab7f1cff79cde515a86f6cc1adbebe8ae25888905561371faf11c8102211f56b487081565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610140565b6101f773ccf3d848e08b94478ed8f46ffead3008faf581fd81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610140565b61012b7f000000000000000000000000000000000000000000000000000000000000000f81565b610102610251366004611b52565b610939565b61017761026436600461199a565b610abc565b61010261027736600461188d565b610c1f565b61010261028a366004611bab565b610d34565b61010261029d366004611bef565b6110e8565b6101026102b0366004611838565b611281565b6040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace690602401600060405180830381600087803b15801561032057600080fd5b505af1158015610334573d6000803e3d6000fd5b505050508063ffffffff166000146103cb576040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace6906024015b600060405180830381600087803b1580156103b257600080fd5b505af11580156103c6573d6000803e3d6000fd5b505050505b5050565b60003073ffffffffffffffffffffffffffffffffffffffff1663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104409190611c0b565b90508073ffffffffffffffffffffffffffffffffffffffff811661056657735a15566417e6c1c9546523066500bddbc53f88c773ffffffffffffffffffffffffffffffffffffffff166365688cc96040518163ffffffff1660e01b81526004016020604051808303816000875af11580156104bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e39190611c0b565b6040517f7a9e5e4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091503090637a9e5e4b90602401600060405180830381600087803b15801561054d57600080fd5b505af1158015610561573d6000803e3d6000fd5b505050505b6040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301527f1cff79cd00000000000000000000000000000000000000000000000000000000604483015282169063b700961390606401602060405180830381865afa1580156105fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106229190611c28565b6106d5576040517fcbeea68c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301527f1cff79cd00000000000000000000000000000000000000000000000000000000604483015282169063cbeea68c906064015b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b505050505b505050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107749190611c0b565b73ffffffffffffffffffffffffffffffffffffffff16146107c1576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b6040805160808082018352606082840181905280830181905267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000e168352600160208085018290528751865173ffffffffffffffffffffffffffffffffffffffff8916928101929092526fffffffffffffffffffffffffffffffff16818701528083018290528551808203909301835292830181815260c0840190955292939092909160a0015b60608152602001906001900390816108735750506040830181905280518291906000906108a2576108a2611c45565b60209081029190910101526040805160028082526060820190925290816020016020820280368337505050606083018190528051600191906000906108e9576108e9611c45565b60200260200101818152505083606001516fffffffffffffffffffffffffffffffff1660001b826060015160018151811061092657610926611c45565b6020026020010181815250505092915050565b3373ffffffffffffffffffffffffffffffffffffffff1673ccf3d848e08b94478ed8f46ffead3008faf581fd73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190611c0b565b73ffffffffffffffffffffffffffffffffffffffff1614610a20576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff84161415610a9b5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610a95573d6000803e3d6000fd5b50505050565b6106d573ffffffffffffffffffffffffffffffffffffffff84168383611368565b6040805160808082018352606082840181905280830181905267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000f1683526001602080850182905287810151865173ffffffffffffffffffffffffffffffffffffffff8916928101929092526fffffffffffffffffffffffffffffffff16818701526000818401528551808203909301835292830181815260c0840190955292939092909160a0015b6060815260200190600190039081610b6d575050604083018190528051829190600090610b9c57610b9c611c45565b60209081029190910101526040805160028082526060820190925290816020016020820280368337505050606083018190528051600091908290610be257610be2611c45565b60200260200101818152505083604001516fffffffffffffffffffffffffffffffff1660001b826060015160018151811061092657610926611c45565b60003073ffffffffffffffffffffffffffffffffffffffff1663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c909190611c0b565b905073ffffffffffffffffffffffffffffffffffffffff8116610cb1575050565b6040517f2bc3217d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301523060248301527f1cff79cd000000000000000000000000000000000000000000000000000000006044830152829190821690632bc3217d906064016106a2565b6000610d4e610d4836849003840184611c74565b306107c4565b6040517ff14283c2000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e909063f14283c290610da39087908590600401611c90565b600060405180830381600087803b158015610dbd57600080fd5b505af1158015610dd1573d6000803e3d6000fd5b50506040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff87166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909250633fb387bd9150602401600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b50610e699250505060a0830160808401611caf565b1561105357610e85610e8036849003840184611c74565b6113f5565b6000610e9f610e9936859003850185611c74565b30610abc565b905063ffffffff8416610f45576040517f3ab9a078000000000000000000000000000000000000000000000000000000008152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a07890610efc908490600401611b3f565b6020604051808303816000875af1158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190611ccc565b5061104d565b6040517ff14283c2000000000000000000000000000000000000000000000000000000008152731612fc28ee0ab882ec99842cde0fc77ff0691e909063f14283c290610f979087908590600401611c90565b600060405180830381600087803b158015610fb157600080fd5b505af1158015610fc5573d6000803e3d6000fd5b50506040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff87166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909250633fb387bd9150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050505b50610a95565b63ffffffff831615610a95576040517fe33cace600000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace690602401600060405180830381600087803b1580156110ca57600080fd5b505af11580156110de573d6000803e3d6000fd5b5050505050505050565b61110573149667b6fae2c63d1b4317c716b0d0e4d3e2bd706103cf565b6000611119610d4836849003840184611c74565b6040517f3ab9a078000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a0789061116c908490600401611b3f565b6020604051808303816000875af115801561118b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111af9190611ccc565b506111c060a0830160808401611caf565b156103cb576111d7610e8036849003840184611c74565b60006111eb610e9936859003850185611c74565b6040517f3ab9a078000000000000000000000000000000000000000000000000000000008152909150731612fc28ee0ab882ec99842cde0fc77ff0691e9090633ab9a0789061123e908490600401611b3f565b6020604051808303816000875af115801561125d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611ccc565b6040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633fb387bd90602401600060405180830381600087803b1580156112ec57600080fd5b505af1158015611300573d6000803e3d6000fd5b505050508063ffffffff166000146103cb576040517f3fb387bd00000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152731612fc28ee0ab882ec99842cde0fc77ff0691e9090633fb387bd90602401610398565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526106d59084906115bf565b80602001516fffffffffffffffffffffffffffffffff1681600001516fffffffffffffffffffffffffffffffff16111561148357805160208201516040517f866a0beb0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff9283166004820152911660248201526044015b60405180910390fd5b80606001516fffffffffffffffffffffffffffffffff1666b1a2bc2ec5000082602001516fffffffffffffffffffffffffffffffff166114c39190611d14565b101561152157602081015160608201516040517f25a5396b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff92831660048201529116602482015260440161147a565b80604001516fffffffffffffffffffffffffffffffff1666b1a2bc2ec5000082600001516fffffffffffffffffffffffffffffffff166115619190611d2b565b11156115bc57805160408083015190517f25a5396b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff92831660048201529116602482015260440161147a565b50565b6000611621826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166116cb9092919063ffffffff16565b8051909150156106d5578080602001905181019061163f9190611c28565b6106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161147a565b60606116da84846000856116e2565b949350505050565b60606116ed856117e6565b611723576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161174c9190611d43565b60006040518083038185875af1925050503d8060008114611789576040519150601f19603f3d011682016040523d82523d6000602084013e61178e565b606091505b509150915081156117a25791506116da9050565b8051156117b25780518082602001fd5b836040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147a9190611d5f565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906116da575050151592915050565b803563ffffffff8116811461183357600080fd5b919050565b6000806040838503121561184b57600080fd5b6118548361181f565b91506118626020840161181f565b90509250929050565b73ffffffffffffffffffffffffffffffffffffffff811681146115bc57600080fd5b60006020828403121561189f57600080fd5b81356118aa8161186b565b9392505050565b80356fffffffffffffffffffffffffffffffff8116811461183357600080fd5b80151581146115bc57600080fd5b600060a082840312156118f157600080fd5b60405160a0810181811067ffffffffffffffff8211171561193b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061194a836118b1565b8152611958602084016118b1565b6020820152611969604084016118b1565b604082015261197a606084016118b1565b6060820152608083013561198d816118d1565b6080919091015292915050565b60008060c083850312156119ad57600080fd5b6119b784846118df565b915060a08301356119c78161186b565b809150509250929050565b60005b838110156119ed5781810151838201526020016119d5565b83811115610a955750506000910152565b60008151808452611a168160208601602086016119d2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501945080840160005b83811015611a7857815187529582019590820190600101611a5c565b509495945050505050565b60006080830167ffffffffffffffff835116845260208084015115158186015260408401516080604087015282815180855260a08801915060a08160051b8901019450838301925060005b81811015611b1a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60898703018352611b088685516119fe565b95509284019291840191600101611ace565b505050505060608301518482036060860152611b368282611a48565b95945050505050565b6020815260006118aa6020830184611a83565b600080600060608486031215611b6757600080fd5b8335611b728161186b565b92506020840135611b828161186b565b929592945050506040919091013590565b600060a08284031215611ba557600080fd5b50919050565b600080600060e08486031215611bc057600080fd5b611bc98461181f565b9250611bd76020850161181f565b9150611be68560408601611b93565b90509250925092565b600060a08284031215611c0157600080fd5b6118aa8383611b93565b600060208284031215611c1d57600080fd5b81516118aa8161186b565b600060208284031215611c3a57600080fd5b81516118aa816118d1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060a08284031215611c8657600080fd5b6118aa83836118df565b63ffffffff831681526040602082015260006116da6040830184611a83565b600060208284031215611cc157600080fd5b81356118aa816118d1565b600060208284031215611cde57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611d2657611d26611ce5565b500390565b60008219821115611d3e57611d3e611ce5565b500190565b60008251611d558184602087016119d2565b9190910192915050565b6020815260006118aa60208301846119fe56fea2646970667358221220e90197807ac04e764cbd235cac1ab25c54b25aa1feec2ec9538c9b4866a6b5d064736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f
-----Decoded View---------------
Arg [0] : _repayBundleId (uint64): 14
Arg [1] : _boostBundleId (uint64): 15
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [1] : 000000000000000000000000000000000000000000000000000000000000000f
Deployed Bytecode Sourcemap
37396:5993:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40752:265;;;;;;:::i;:::-;;:::i;:::-;;37490:39;;;;;;;;617:18:1;605:31;;;587:50;;575:2;560:18;37490:39:0;;;;;;;;13917:555;;;;;;:::i;:::-;;:::i;11503:85::-;;;:::i;41817:721::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;13686:85::-;;13735:35;13686:85;;;;;5456:66:1;5444:79;;;5426:98;;5414:2;5399:18;13686:85:0;5282:248:1;10674:68:0;;9491:42;10674:68;;;;;5729:42:1;5717:55;;;5699:74;;5687:2;5672:18;10674:68:0;5535:244:1;37536:39:0;;;;;11141:316;;;;;;:::i;:::-;;:::i;42666:720::-;;;;;;:::i;:::-;;:::i;14649:428::-;;;;;;:::i;:::-;;:::i;39239:1110::-;;;;;;:::i;:::-;;:::i;38498:549::-;;;;;;:::i;:::-;;:::i;40420:259::-;;;;;;:::i;:::-;;:::i;40752:265::-;40850:51;;;;;7273:10:1;7261:23;;40850:51:0;;;7243:42:1;29438::0;;40850;;7216:18:1;;40850:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40918:7;:12;;40929:1;40918:12;40914:96;;40947:51;;;;;7273:10:1;7261:23;;40947:51:0;;;7243:42:1;29438::0;;40947;;7216:18:1;;40947:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40914:96;40752:265;;:::o;13917:555::-;13982:21;14029:4;14014:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13982:66;-1:-1:-1;13982:66:0;14114:27;;;14110:188;;9584:42;14166:40;;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14223:63;;;;;5729:42:1;5717:55;;14223:63:0;;;5699:74:1;14158:50:0;;-1:-1:-1;14238:4:0;;14223:34;;5672:18:1;;14223:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14110:188;14315:61;;;;;:13;8371:15:1;;;14315:61:0;;;8353:34:1;14352:4:0;8403:18:1;;;8396:43;8475:79;8455:18;;;8448:107;14315:13:0;;;;;8265:18:1;;14315:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14310:155;;14393:60;;;;;:12;8371:15:1;;;14393:60:0;;;8353:34:1;14429:4:0;8403:18:1;;;8396:43;8475:79;8455:18;;;8448:107;14393:12:0;;;;;8265:18:1;;14393:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14310:155;13971:501;;13917:555;:::o;11503:85::-;11015:10;10993:32;;9491:42;10993:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;;;10989:87;;11048:16;;;;;;;;;;;;;;10989:87;11568:10:::1;11547:33;41817:721:::0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;41955:45:0;41985:15;41955:45;;;42031:4;-1:-1:-1;;;;42011:24:0;;;42175:17;;42148:71;;9964:42:1;9952:55;;42148:71:0;;;9934:74:1;;;;42167:26:0;;10024:18:1;;;10017:34;10067:18;;;10060:45;;;42148:71:0;;;;;;;;;;9907:18:1;;;42254:14:0;;;;;;;;;-1:-1:-1;;42148:71:0;;9907:18:1;;42254:14:0;;;;;;;;;;;;;;;;-1:-1:-1;;42230:20:0;;;:38;;;42279:23;;42305:11;;42230:38;42300:1;;42279:23;;;;:::i;:::-;;;;;;;;;;:37;42349:16;;;42363:1;42349:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;42329:16:0;;;:36;;;42376:19;;42414:1;;42329:36;42398:19;;42376;;;;:::i;:::-;;;;;;:41;;;;;42488:8;:25;;;42480:34;;42472:43;;42450:8;:16;;;42467:1;42450:19;;;;;;;;:::i;:::-;;;;;;:65;;;;;41944:594;41817:721;;;;:::o;11141:316::-;10869:10;10847:32;;9491:42;10847:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;;;10843:87;;10902:16;;;;;;;;;;;;;;10843:87;11263:42:::1;11253:52;::::0;::::1;;11249:201;;;11322:36;::::0;:27:::1;::::0;::::1;::::0;:36;::::1;;;::::0;11350:7;;11322:36:::1;::::0;;;11350:7;11322:27;:36;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;13971:501:::0;;13917:555;:::o;11249:201::-:1;11391:47;:27;::::0;::::1;11419:9:::0;11430:7;11391:27:::1;:47::i;42666:720::-:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;42804:45:0;42834:15;42804:45;;;42880:4;-1:-1:-1;;;;42860:24:0;;;43024:17;;;;42997:70;;9964:42:1;9952:55;;42997:70:0;;;9934:74:1;;;;43016:26:0;;10024:18:1;;;10017:34;-1:-1:-1;10067:18:1;;;10060:45;42997:70:0;;;;;;;;;;9907:18:1;;;43102:14:0;;;;;;;;;-1:-1:-1;;42997:70:0;;9907:18:1;;43102:14:0;;;;;;;;;;;;;;;;-1:-1:-1;;43078:20:0;;;:38;;;43127:23;;43153:11;;43078:38;43148:1;;43127:23;;;;:::i;:::-;;;;;;;;;;:37;43197:16;;;43211:1;43197:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;43177:16:0;;;:36;;;43224:19;;43262:1;;43177:36;43262:1;;43224:19;;;;:::i;:::-;;;;;;:41;;;;;43336:8;:25;;;43328:34;;43320:43;;43298:8;:16;;;43315:1;43298:19;;;;;;;;:::i;14649:428::-;14716:21;14763:4;14748:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14716:66;-1:-1:-1;14886:27:0;;;14882:66;;14930:7;14649:428;:::o;14882:66::-;15009:60;;;;;:12;8371:15:1;;;15009:60:0;;;8353:34:1;15045:4:0;8403:18:1;;;8396:43;8475:79;8455:18;;;8448:107;14984:13:0;;15009:12;;;;;;8265:18:1;;15009:60:0;8092:469:1;39239:1110:0;39467:27;39497:39;;;;;;;;39512:8;39497:39;:::i;:::-;39530:4;39497:14;:39::i;:::-;39547:61;;;;;39467:69;;-1:-1:-1;29438:42:0;;39547;;:61;;39590:7;;39467:69;;39547:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;39619:49:0;;;;;7273:10:1;7261:23;;39619:49:0;;;7243:42:1;29438::0;;-1:-1:-1;39619:40:0;;-1:-1:-1;7216:18:1;;39619:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39685:21:0;;-1:-1:-1;;;39685:21:0;;;;;;;:::i;:::-;39681:661;;;39723:26;;;;;;;;39740:8;39723:26;:::i;:::-;:16;:26::i;:::-;39766:27;39796:39;;;;;;;;39811:8;39796:39;:::i;:::-;39829:4;39796:14;:39::i;:::-;39766:69;-1:-1:-1;39918:12:0;;;39914:281;;39951:58;;;;;29438:42;;39951:48;;:58;;40000:8;;39951:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;39914:281;;;40050:61;;;;;29438:42;;40050;;:61;;40093:7;;40102:8;;40050:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;40130:49:0;;;;;7273:10:1;7261:23;;40130:49:0;;;7243:42:1;29438::0;;-1:-1:-1;40130:40:0;;-1:-1:-1;7216:18:1;;40130:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39914:281;39708:498;39681:661;;;40231:12;;;;40227:104;;40264:51;;;;;7273:10:1;7261:23;;40264:51:0;;;7243:42:1;29438::0;;40264;;7216:18:1;;40264:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39374:975;39239:1110;;;:::o;38498:549::-;38608:31;29248:42;38608:14;:31::i;:::-;38650:27;38680:39;;;;;;;;38695:8;38680:39;:::i;:::-;38732:58;;;;;38650:69;;-1:-1:-1;29438:42:0;;38732:48;;:58;;38650:69;;38732:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;38805:21:0;;;;;;;;:::i;:::-;38801:239;;;38843:26;;;;;;;;38860:8;38843:26;:::i;:::-;38886:27;38916:39;;;;;;;;38931:8;38916:39;:::i;:::-;38970:58;;;;;38886:69;;-1:-1:-1;29438:42:0;;38970:48;;:58;;38886:69;;38970:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;40420:259::-;40516:49;;;;;7273:10:1;7261:23;;40516:49:0;;;7243:42:1;29438::0;;40516:40;;7216:18:1;;40516:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40582:7;:12;;40593:1;40582:12;40578:94;;40611:49;;;;;7273:10:1;7261:23;;40611:49:0;;;7243:42:1;29438::0;;40611:40;;7216:18:1;;40611:49:0;7098:193:1;6605:211:0;6749:58;;;11563:42:1;11551:55;;6749:58:0;;;11533:74:1;11623:18;;;;11616:34;;;6749:58:0;;;;;;;;;;11506:18:1;;;;6749:58:0;;;;;;;;;;6772:23;6749:58;;;6722:86;;6742:5;;6722:19;:86::i;41119:570::-;41231:8;:17;;;41211:37;;:8;:17;;;:37;;;41207:129;;;41287:17;;41306;;;;41272:52;;;;;11845:34:1;11906:15;;;41272:52:0;;;11888:34:1;11958:15;;11938:18;;;11931:43;11808:18;;41272:52:0;;;;;;;;41207:129;41389:8;:25;;;41352:62;;37859:17;41353:8;:17;;;:32;;;;;;:::i;:::-;41352:62;41348:161;;;41452:17;;;;41471:25;;;;41438:59;;;;;11845:34:1;11906:15;;;41438:59:0;;;11888:34:1;11958:15;;11938:18;;;11931:43;11808:18;;41438:59:0;11661:319:1;41348:161:0;41562:8;:25;;;41525:62;;37859:17;41526:8;:17;;;:32;;;;;;:::i;:::-;41525:62;41521:161;;;41625:17;;41644:25;;;;;41611:59;;;;;11845:34:1;11906:15;;;41611:59:0;;;11888:34:1;11958:15;;11938:18;;;11931:43;11808:18;;41611:59:0;11661:319:1;41521:161:0;41119:570;:::o;8355:468::-;8436:23;8462:106;8504:4;8462:106;;;;;;;;;;;;;;;;;8470:5;8462:27;;;;:106;;;;;:::i;:::-;8583:17;;8436:132;;-1:-1:-1;8583:21:0;8579:237;;8738:10;8727:30;;;;;;;;;;;;:::i;:::-;8719:85;;;;;;;12639:2:1;8719:85:0;;;12621:21:1;12678:2;12658:18;;;12651:30;12717:34;12697:18;;;12690:62;12788:12;12768:18;;;12761:40;12818:19;;8719:85:0;12437:406:1;2627:230:0;2764:12;2796:53;2819:6;2827:4;2833:1;2836:12;2796:22;:53::i;:::-;2789:60;2627:230;-1:-1:-1;;;;2627:230:0:o;3577:1036::-;3750:12;3781:18;3792:6;3781:10;:18::i;:::-;3775:77;;3823:17;;;;;;;;;;;;;;3775:77;3925:12;3939:23;3966:6;:11;;3985:8;3995:4;3966:34;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3924:76;;;;4015:7;4011:595;;;4046:10;-1:-1:-1;4039:17:0;;-1:-1:-1;4039:17:0;4011:595;4160:17;;:21;4156:439;;4423:10;4417:17;4484:15;4471:10;4467:2;4463:19;4456:44;4156:439;4566:12;4559:20;;;;;;;;;;;:::i;1337:641::-;1397:4;1878:20;;1708:66;1927:23;;;;;;:42;;-1:-1:-1;;1954:15:0;;;1919:51;-1:-1:-1;;1337:641:0:o;14:163:1:-;81:20;;141:10;130:22;;120:33;;110:61;;167:1;164;157:12;110:61;14:163;;;:::o;182:256::-;248:6;256;309:2;297:9;288:7;284:23;280:32;277:52;;;325:1;322;315:12;277:52;348:28;366:9;348:28;:::i;:::-;338:38;;395:37;428:2;417:9;413:18;395:37;:::i;:::-;385:47;;182:256;;;;;:::o;648:154::-;734:42;727:5;723:54;716:5;713:65;703:93;;792:1;789;782:12;807:247;866:6;919:2;907:9;898:7;894:23;890:32;887:52;;;935:1;932;925:12;887:52;974:9;961:23;993:31;1018:5;993:31;:::i;:::-;1043:5;807:247;-1:-1:-1;;;807:247:1:o;1248:188::-;1316:20;;1376:34;1365:46;;1355:57;;1345:85;;1426:1;1423;1416:12;1441:118;1527:5;1520:13;1513:21;1506:5;1503:32;1493:60;;1549:1;1546;1539:12;1564:932;1630:5;1678:4;1666:9;1661:3;1657:19;1653:30;1650:50;;;1696:1;1693;1686:12;1650:50;1729:2;1723:9;1771:4;1763:6;1759:17;1842:6;1830:10;1827:22;1806:18;1794:10;1791:34;1788:62;1785:242;;;1883:77;1880:1;1873:88;1984:4;1981:1;1974:15;2012:4;2009:1;2002:15;1785:242;2043:2;2036:22;2076:6;-1:-1:-1;2076:6:1;2106:29;2125:9;2106:29;:::i;:::-;2098:6;2091:45;2169:38;2203:2;2192:9;2188:18;2169:38;:::i;:::-;2164:2;2156:6;2152:15;2145:63;2241:38;2275:2;2264:9;2260:18;2241:38;:::i;:::-;2236:2;2228:6;2224:15;2217:63;2313:38;2347:2;2336:9;2332:18;2313:38;:::i;:::-;2308:2;2300:6;2296:15;2289:63;2404:3;2393:9;2389:19;2376:33;2418:30;2440:7;2418:30;:::i;:::-;2476:3;2464:16;;;;2457:33;1564:932;;-1:-1:-1;;1564:932:1:o;2501:388::-;2606:6;2614;2667:3;2655:9;2646:7;2642:23;2638:33;2635:53;;;2684:1;2681;2674:12;2635:53;2707:57;2756:7;2745:9;2707:57;:::i;:::-;2697:67;;2814:3;2803:9;2799:19;2786:33;2828:31;2853:5;2828:31;:::i;:::-;2878:5;2868:15;;;2501:388;;;;;:::o;2894:258::-;2966:1;2976:113;2990:6;2987:1;2984:13;2976:113;;;3066:11;;;3060:18;3047:11;;;3040:39;3012:2;3005:10;2976:113;;;3107:6;3104:1;3101:13;3098:48;;;-1:-1:-1;;3142:1:1;3124:16;;3117:27;2894:258::o;3157:316::-;3198:3;3236:5;3230:12;3263:6;3258:3;3251:19;3279:63;3335:6;3328:4;3323:3;3319:14;3312:4;3305:5;3301:16;3279:63;:::i;:::-;3387:2;3375:15;3392:66;3371:88;3362:98;;;;3462:4;3358:109;;3157:316;-1:-1:-1;;3157:316:1:o;3478:435::-;3531:3;3569:5;3563:12;3596:6;3591:3;3584:19;3622:4;3651:2;3646:3;3642:12;3635:19;;3688:2;3681:5;3677:14;3709:1;3719:169;3733:6;3730:1;3727:13;3719:169;;;3794:13;;3782:26;;3828:12;;;;3863:15;;;;3755:1;3748:9;3719:169;;;-1:-1:-1;3904:3:1;;3478:435;-1:-1:-1;;;;;3478:435:1:o;3918:1084::-;3972:3;4011:4;4006:3;4002:14;4055:18;4047:5;4041:12;4037:37;4032:3;4025:50;4094:4;4159:2;4152:5;4148:14;4142:21;4135:29;4128:37;4123:2;4118:3;4114:12;4107:59;4212:4;4205:5;4201:16;4195:23;4250:4;4243;4238:3;4234:14;4227:28;4277:4;4310:12;4304:19;4345:6;4339:4;4332:20;4379:3;4374;4370:13;4361:22;;4436:3;4426:6;4423:1;4419:14;4414:3;4410:24;4406:34;4392:48;;4481:2;4467:12;4463:21;4449:35;;4502:1;4512:313;4526:6;4523:1;4520:13;4512:313;;;4611:66;4605:3;4597:6;4593:16;4589:89;4582:5;4575:104;4702:39;4734:6;4725;4719:13;4702:39;:::i;:::-;4692:49;-1:-1:-1;4764:15:1;;;;4801:14;;;;4548:1;4541:9;4512:313;;;4516:3;;;;;4873:4;4866:5;4862:16;4856:23;4923:3;4915:6;4911:16;4904:4;4899:3;4895:14;4888:40;4944:52;4989:6;4973:14;4944:52;:::i;:::-;4937:59;3918:1084;-1:-1:-1;;;;;3918:1084:1:o;5007:270::-;5194:2;5183:9;5176:21;5157:4;5214:57;5267:2;5256:9;5252:18;5244:6;5214:57;:::i;5784:456::-;5861:6;5869;5877;5930:2;5918:9;5909:7;5905:23;5901:32;5898:52;;;5946:1;5943;5936:12;5898:52;5985:9;5972:23;6004:31;6029:5;6004:31;:::i;:::-;6054:5;-1:-1:-1;6111:2:1;6096:18;;6083:32;6124:33;6083:32;6124:33;:::i;:::-;5784:456;;6176:7;;-1:-1:-1;;;6230:2:1;6215:18;;;;6202:32;;5784:456::o;6245:168::-;6317:5;6362:3;6353:6;6348:3;6344:16;6340:26;6337:46;;;6379:1;6376;6369:12;6337:46;-1:-1:-1;6401:6:1;6245:168;-1:-1:-1;6245:168:1:o;6418:407::-;6532:6;6540;6548;6601:3;6589:9;6580:7;6576:23;6572:33;6569:53;;;6618:1;6615;6608:12;6569:53;6641:28;6659:9;6641:28;:::i;:::-;6631:38;;6688:37;6721:2;6710:9;6706:18;6688:37;:::i;:::-;6678:47;;6744:75;6811:7;6806:2;6795:9;6791:18;6744:75;:::i;:::-;6734:85;;6418:407;;;;;:::o;6830:263::-;6928:6;6981:3;6969:9;6960:7;6956:23;6952:33;6949:53;;;6998:1;6995;6988:12;6949:53;7021:66;7079:7;7068:9;7021:66;:::i;7296:270::-;7385:6;7438:2;7426:9;7417:7;7413:23;7409:32;7406:52;;;7454:1;7451;7444:12;7406:52;7486:9;7480:16;7505:31;7530:5;7505:31;:::i;8566:245::-;8633:6;8686:2;8674:9;8665:7;8661:23;8657:32;8654:52;;;8702:1;8699;8692:12;8654:52;8734:9;8728:16;8753:28;8775:5;8753:28;:::i;10116:184::-;10168:77;10165:1;10158:88;10265:4;10262:1;10255:15;10289:4;10286:1;10279:15;10305:252;10401:6;10454:3;10442:9;10433:7;10429:23;10425:33;10422:53;;;10471:1;10468;10461:12;10422:53;10494:57;10543:7;10532:9;10494:57;:::i;10562:357::-;10788:10;10780:6;10776:23;10765:9;10758:42;10836:2;10831;10820:9;10816:18;10809:30;10739:4;10856:57;10909:2;10898:9;10894:18;10886:6;10856:57;:::i;10924:241::-;10980:6;11033:2;11021:9;11012:7;11008:23;11004:32;11001:52;;;11049:1;11046;11039:12;11001:52;11088:9;11075:23;11107:28;11129:5;11107:28;:::i;11170:184::-;11240:6;11293:2;11281:9;11272:7;11268:23;11264:32;11261:52;;;11309:1;11306;11299:12;11261:52;-1:-1:-1;11332:16:1;;11170:184;-1:-1:-1;11170:184:1:o;11985:::-;12037:77;12034:1;12027:88;12134:4;12131:1;12124:15;12158:4;12155:1;12148:15;12174:125;12214:4;12242:1;12239;12236:8;12233:34;;;12247:18;;:::i;:::-;-1:-1:-1;12284:9:1;;12174:125::o;12304:128::-;12344:3;12375:1;12371:6;12368:1;12365:13;12362:39;;;12381:18;;:::i;:::-;-1:-1:-1;12417:9:1;;12304:128::o;12848:274::-;12977:3;13015:6;13009:13;13031:53;13077:6;13072:3;13065:4;13057:6;13053:17;13031:53;:::i;:::-;13100:16;;;;;12848:274;-1:-1:-1;;12848:274:1:o;13127:219::-;13276:2;13265:9;13258:21;13239:4;13296:44;13336:2;13325:9;13321:18;13313:6;13296:44;:::i
Swarm Source
ipfs://e90197807ac04e764cbd235cac1ab25c54b25aa1feec2ec9538c9b4866a6b5d0
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 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.