Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Loading...
Loading
Contract Name:
PositionSettingsRegistry
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Sickle } from "contracts/Sickle.sol"; import { SickleFactory } from "contracts/SickleFactory.sol"; import { ConnectorRegistry } from "contracts/ConnectorRegistry.sol"; import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol"; import { Farm } from "contracts/structs/FarmStrategyStructs.sol"; import { PositionKey, RewardBehavior, RewardConfig, ExitConfig, PositionSettings } from "contracts/structs/PositionSettingsStructs.sol"; import { ILiquidityConnector } from "contracts/interfaces/ILiquidityConnector.sol"; import { IPositionSettingsRegistry } from "contracts/interfaces/IPositionSettingsRegistry.sol"; struct PreviousExitConfig { uint256 triggerPriceHigh; uint256 triggerPriceLow; uint256 triggerReserves0; uint256 triggerReserves1; address exitTokenOutLow; address exitTokenOutHigh; uint256 priceImpactBP; uint256 slippageBP; } struct PreviousPositionSettings { address pair; address router; bool automateRewards; RewardConfig rewardConfig; bool autoExit; PreviousExitConfig exitConfig; } interface IPreviousSettingsRegistry { function getPositionSettings( PositionKey calldata key ) external view returns (PreviousPositionSettings memory); } contract PositionSettingsRegistry is TimelockAdmin, IPositionSettingsRegistry { uint256 constant MAX_SLIPPAGE_BP = 500; uint256 constant MAX_PRICE_IMPACT_BP = 5000; SickleFactory public immutable factory; ConnectorRegistry private _connectorRegistry; mapping(bytes32 => PositionSettings) positionSettingsMap; constructor( SickleFactory _factory, ConnectorRegistry connectorRegistry, address timelockAdmin ) TimelockAdmin(timelockAdmin) { factory = _factory; _connectorRegistry = connectorRegistry; emit ConnectionRegistrySet(address(connectorRegistry)); } /* Timelock functions */ function setConnectorRegistry( ConnectorRegistry connectorRegistry ) external onlyTimelockAdmin { _connectorRegistry = connectorRegistry; emit ConnectionRegistrySet(address(connectorRegistry)); } /* Public functions */ function getPositionSettings( PositionKey calldata key ) public view returns (PositionSettings memory) { bytes32 keyHash = keccak256(abi.encode(key)); return positionSettingsMap[keyHash]; } /* Owner functions */ function setPositionSettings( Farm calldata farm, PositionSettings calldata settings ) external checkPositionSettings(farm.stakingContract, settings) { PositionKey memory key = PositionKey({ sickle: _getSickleByOwner(msg.sender), stakingContract: farm.stakingContract, poolIndex: farm.poolIndex }); bytes32 keyHash = keccak256(abi.encode(key)); positionSettingsMap[keyHash] = settings; emit PositionSettingsSet(key, settings); } /* Sickle (delegatecall) functions */ function setPositionSettings( PositionKey calldata key, PositionSettings calldata settings ) external checkPositionSettings(key.stakingContract, settings) { Sickle sickle = Sickle(payable(msg.sender)); if (key.sickle != sickle) { revert OnlySickle(); } bytes32 keyHash = keccak256(abi.encode(key)); positionSettingsMap[keyHash] = settings; emit PositionSettingsSet(key, settings); } // Used to set reward behavior (but not auto-exit) for multiple positions function setMultiplePositionSettings( Farm[] calldata farms, RewardConfig calldata rewardConfig ) public checkRewardConfig(rewardConfig) { Sickle sickle = _getSickleByOwner(msg.sender); PositionKey memory key; for (uint256 i; i < farms.length; i++) { key = PositionKey({ sickle: sickle, stakingContract: farms[i].stakingContract, poolIndex: farms[i].poolIndex }); bytes32 keyHash = keccak256(abi.encode(key)); positionSettingsMap[keyHash].automateRewards = true; positionSettingsMap[keyHash].rewardConfig = rewardConfig; emit PositionSettingsSet(key, positionSettingsMap[keyHash]); } } function migratePositionSettings( IPreviousSettingsRegistry previousPositionSettings, PositionKey[] calldata keys ) external { Sickle sickle = _getSickleByOwner(msg.sender); for (uint256 i; i < keys.length; i++) { if (keys[i].sickle != sickle) { revert OnlySickle(); } PreviousPositionSettings memory previousSettings = previousPositionSettings.getPositionSettings(keys[i]); PositionSettings memory settings = PositionSettings({ pool: previousSettings.pair, router: previousSettings.router, automateRewards: previousSettings.automateRewards, rewardConfig: previousSettings.rewardConfig, autoExit: previousSettings.autoExit, exitConfig: ExitConfig({ baseTokenIndex: 0, quoteTokenIndex: 1, triggerPriceLow: previousSettings.exitConfig.triggerPriceLow, exitTokenOutLow: previousSettings.exitConfig.exitTokenOutLow, triggerPriceHigh: previousSettings.exitConfig.triggerPriceHigh, exitTokenOutHigh: previousSettings.exitConfig.exitTokenOutHigh, triggerReservesLow: new uint256[](2), triggerReservesTokensOut: new address[](2), priceImpactBP: previousSettings.exitConfig.priceImpactBP, slippageBP: previousSettings.exitConfig.slippageBP }), extraData: "" }); settings.exitConfig.triggerReservesLow[0] = previousSettings.exitConfig.triggerReserves0; settings.exitConfig.triggerReservesLow[1] = previousSettings.exitConfig.triggerReserves1; settings.exitConfig.triggerReservesTokensOut[0] = previousSettings.exitConfig.exitTokenOutLow; settings.exitConfig.triggerReservesTokensOut[1] = previousSettings.exitConfig.exitTokenOutHigh; bytes32 keyHash = keccak256(abi.encode(keys[i])); positionSettingsMap[keyHash] = settings; emit PositionSettingsSet(keys[i], settings); } } function validateHarvestFor( PositionKey calldata key ) public view { PositionSettings memory settings = getPositionSettings(key); if ( !settings.automateRewards || settings.rewardConfig.rewardBehavior != RewardBehavior.Harvest ) { revert AutoHarvestNotSet(); } } function validateCompoundFor( PositionKey calldata key ) public view { PositionSettings memory settings = getPositionSettings(key); if ( !settings.automateRewards || settings.rewardConfig.rewardBehavior != RewardBehavior.Compound ) { revert AutoCompoundNotSet(); } } function validateExitFor( PositionKey calldata key ) public view { PositionSettings memory settings = getPositionSettings(key); ExitConfig memory config = settings.exitConfig; if (!settings.autoExit) { revert AutoExitNotSet(); } ILiquidityConnector connector = ILiquidityConnector( _connectorRegistry.connectorOf(address(settings.router)) ); uint256 price = connector.getPoolPrice( address(settings.pool), config.baseTokenIndex, config.quoteTokenIndex ); bool priceBelowRange = price < config.triggerPriceLow; bool priceAboveRange = price > config.triggerPriceHigh; bool reservesBelowRange = false; if (config.triggerReservesLow.length > 0) { uint256[] memory reserves = connector.getReserves(address(settings.pool)); for (uint256 i; i < config.triggerReservesLow.length; i++) { if (reserves[i] < config.triggerReservesLow[i]) { reservesBelowRange = true; break; } } } if (!priceBelowRange && !priceAboveRange && !reservesBelowRange) { revert ConditionsNotMet(); } } /* Modifiers */ modifier checkPositionSettings( address stakingContract, PositionSettings memory settings ) { if (stakingContract == address(0)) { revert InvalidStakingContract(); } if (settings.automateRewards) { _checkRewardConfig(settings.rewardConfig); } else { if ( settings.rewardConfig.rewardBehavior != RewardBehavior.None || settings.rewardConfig.harvestTokenOut != address(0) ) { revert NonZeroRewardConfig(); } } if (settings.autoExit) { _checkExitConfig(settings); } else { if ( settings.exitConfig.triggerPriceLow != 0 || settings.exitConfig.exitTokenOutLow != address(0) || settings.exitConfig.triggerPriceHigh != 0 || settings.exitConfig.exitTokenOutHigh != address(0) || settings.exitConfig.slippageBP != 0 || settings.exitConfig.priceImpactBP != 0 || settings.exitConfig.triggerReservesLow.length > 0 || settings.exitConfig.triggerReservesTokensOut.length > 0 || settings.exitConfig.baseTokenIndex != 0 || settings.exitConfig.quoteTokenIndex != 0 ) { revert NonZeroExitConfig(); } } _; } modifier checkRewardConfig( RewardConfig memory rewardConfig ) { _checkRewardConfig(rewardConfig); _; } /* Internal */ function _checkRewardConfig( RewardConfig memory rewardConfig ) private pure { if (rewardConfig.rewardBehavior == RewardBehavior.None) { revert RewardBehaviorNotSet(); } if ( rewardConfig.rewardBehavior == RewardBehavior.Compound && rewardConfig.harvestTokenOut != address(0) ) { revert InvalidTokenOut(); } } function _checkExitConfig( PositionSettings memory settings ) private view { if (settings.pool == address(0)) { revert InvalidPool(); } if (settings.router == address(0)) { revert InvalidRouter(); } if ( settings.exitConfig.triggerPriceLow == 0 && settings.exitConfig.triggerPriceHigh == 0 ) { revert ExitTriggersNotSet(); } if ( settings.exitConfig.triggerPriceLow >= settings.exitConfig.triggerPriceHigh ) { revert InvalidExitTriggers(); } if (settings.exitConfig.slippageBP > MAX_SLIPPAGE_BP) { revert InvalidSlippageBP(); } if ( settings.exitConfig.priceImpactBP > MAX_PRICE_IMPACT_BP || settings.exitConfig.priceImpactBP == 0 ) { revert InvalidPriceImpactBP(); } if ( settings.exitConfig.triggerReservesLow.length != settings.exitConfig.triggerReservesTokensOut.length ) { revert InvalidTriggerReserves(); } ILiquidityConnector connector = ILiquidityConnector( _connectorRegistry.connectorOf(address(settings.router)) ); uint256[] memory reserves = connector.getReserves(address(settings.pool)); if ( settings.exitConfig.baseTokenIndex >= reserves.length || settings.exitConfig.quoteTokenIndex >= reserves.length || settings.exitConfig.baseTokenIndex == settings.exitConfig.quoteTokenIndex ) { revert InvalidTokenIndices(); } if (settings.exitConfig.triggerReservesLow.length > 0) { if ( reserves.length != settings.exitConfig.triggerReservesLow.length ) { revert InvalidTriggerReserves(); } } } function _getSickleByOwner( address owner ) private view returns (Sickle) { address sickle = factory.sickles(owner); if (sickle == address(0)) { revert SickleNotDeployed(); } return Sickle(payable(sickle)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { SickleStorage } from "contracts/base/SickleStorage.sol"; import { Multicall } from "contracts/base/Multicall.sol"; import { SickleRegistry } from "contracts/SickleRegistry.sol"; /// @title Sickle contract /// @author vfat.tools /// @notice Sickle facilitates farming and interactions with Masterchef /// contracts /// @dev Base contract inheriting from all the other "manager" contracts contract Sickle is SickleStorage, Multicall { /// @notice Function to receive ETH receive() external payable { } /// @param sickleRegistry_ Address of the SickleRegistry contract constructor( SickleRegistry sickleRegistry_ ) Multicall(sickleRegistry_) { _disableInitializers(); } /// @param sickleOwner_ Address of the Sickle owner function initialize( address sickleOwner_, address approved_ ) external initializer { SickleStorage._initializeSickleStorage(sickleOwner_, approved_); } /// INTERNALS /// function onERC721Received( address, // operator address, // from uint256, // tokenId bytes calldata // data ) external pure returns (bytes4) { return this.onERC721Received.selector; } function onERC1155Received( address, // operator address, // from uint256, // id uint256, // value bytes calldata // data ) external pure returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, // operator address, // from uint256[] calldata, // ids uint256[] calldata, // values bytes calldata // data ) external pure returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol"; import { Sickle } from "contracts/Sickle.sol"; import { SickleRegistry } from "contracts/SickleRegistry.sol"; import { Admin } from "contracts/base/Admin.sol"; /// @title SickleFactory contract /// @author vfat.tools /// @notice Factory deploying new Sickle contracts contract SickleFactory is Admin { /// EVENTS /// /// @notice Emitted when a new Sickle contract is deployed /// @param admin Address receiving the admin rights of the Sickle contract /// @param sickle Address of the newly deployed Sickle contract event Deploy(address indexed admin, address sickle); /// @notice Thrown when the caller is not whitelisted /// @param caller Address of the non-whitelisted caller error CallerNotWhitelisted(address caller); // 0x252c8273 /// @notice Thrown when the factory is not active and a deploy is attempted error NotActive(); // 0x80cb55e2 /// @notice Thrown when a Sickle contract is already deployed for a user error SickleAlreadyDeployed(); //0xf6782ef1 /// STORAGE /// mapping(address => address) private _sickles; mapping(address => address) private _admins; mapping(address => bytes32) public _referralCodes; /// @notice Address of the SickleRegistry contract SickleRegistry public immutable registry; /// @notice Address of the Sickle implementation contract address public immutable implementation; /// @notice Address of the previous SickleFactory contract (if applicable) SickleFactory public immutable previousFactory; /// @notice Whether the factory is active (can deploy new Sickle contracts) bool public isActive = true; /// WRITE FUNCTIONS /// /// @param admin_ Address of the admin /// @param sickleRegistry_ Address of the SickleRegistry contract /// @param sickleImplementation_ Address of the Sickle implementation /// contract /// @param previousFactory_ Address of the previous SickleFactory contract /// if applicable constructor( address admin_, address sickleRegistry_, address sickleImplementation_, address previousFactory_ ) Admin(admin_) { registry = SickleRegistry(sickleRegistry_); implementation = sickleImplementation_; previousFactory = SickleFactory(previousFactory_); } function setActive( bool active ) external onlyAdmin { isActive = active; } function _deploy( address admin, address approved, bytes32 referralCode ) internal returns (address sickle) { sickle = Clones.cloneDeterministic( implementation, keccak256(abi.encode(admin)) ); Sickle(payable(sickle)).initialize(admin, approved); _sickles[admin] = sickle; _admins[sickle] = admin; if (referralCode != bytes32(0)) { _referralCodes[sickle] = referralCode; } emit Deploy(admin, sickle); } function _getSickle( address admin ) internal returns (address sickle) { sickle = _sickles[admin]; if (sickle != address(0)) { return sickle; } if (address(previousFactory) != address(0)) { sickle = previousFactory.sickles(admin); if (sickle != address(0)) { _sickles[admin] = sickle; _admins[sickle] = admin; _referralCodes[sickle] = previousFactory.referralCodes(sickle); return sickle; } } } /// @notice Predict the address of a Sickle contract for a specific user /// @param admin Address receiving the admin rights of the Sickle contract /// @return sickle Address of the predicted Sickle contract function predict( address admin ) external view returns (address) { bytes32 salt = keccak256(abi.encode(admin)); return Clones.predictDeterministicAddress(implementation, salt); } /// @notice Returns the Sickle contract for a specific user /// @param admin Address that owns the Sickle contract /// @return sickle Address of the Sickle contract function sickles( address admin ) external view returns (address sickle) { sickle = _sickles[admin]; if (sickle == address(0) && address(previousFactory) != address(0)) { sickle = previousFactory.sickles(admin); } } /// @notice Returns the admin for a specific Sickle contract /// @param sickle Address of the Sickle contract /// @return admin Address that owns the Sickle contract function admins( address sickle ) external view returns (address admin) { admin = _admins[sickle]; if (admin == address(0) && address(previousFactory) != address(0)) { admin = previousFactory.admins(sickle); } } /// @notice Returns the referral code for a specific Sickle contract /// @param sickle Address of the Sickle contract /// @return referralCode Referral code for the user function referralCodes( address sickle ) external view returns (bytes32 referralCode) { referralCode = _referralCodes[sickle]; if ( referralCode == bytes32(0) && address(previousFactory) != address(0) ) { referralCode = previousFactory.referralCodes(sickle); } } /// @notice Deploys a new Sickle contract for a specific user, or returns /// the existing one if it exists /// @param admin Address receiving the admin rights of the Sickle contract /// @param approved Address approved to manage automation /// @param referralCode Referral code for the user /// @return sickle Address of the deployed Sickle contract function getOrDeploy( address admin, address approved, bytes32 referralCode ) external returns (address sickle) { if (!isActive) { revert NotActive(); } if (!registry.isWhitelistedCaller(msg.sender)) { revert CallerNotWhitelisted(msg.sender); } if ((sickle = _getSickle(admin)) != address(0)) { return sickle; } return _deploy(admin, approved, referralCode); } /// @notice Deploys a new Sickle contract for a specific user /// @dev Sickle contracts are deployed with create2, the address of the /// admin is used as a salt, so all the Sickle addresses can be pre-computed /// and only 1 Sickle will exist per address /// @param approved Address approved to manage automation /// @param referralCode Referral code for the user /// @return sickle Address of the deployed Sickle contract function deploy( address approved, bytes32 referralCode ) external returns (address sickle) { if (!isActive) { revert NotActive(); } if (_getSickle(msg.sender) != address(0)) { revert SickleAlreadyDeployed(); } return _deploy(msg.sender, approved, referralCode); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Admin } from "contracts/base/Admin.sol"; import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol"; error ConnectorNotRegistered(address target); error CustomRegistryAlreadyRegistered(); interface ICustomConnectorRegistry { function connectorOf( address target ) external view returns (address); } contract ConnectorRegistry is Admin, TimelockAdmin { event ConnectorChanged(address target, address connector); event CustomRegistryAdded(address registry); event CustomRegistryRemoved(address registry); error ConnectorAlreadySet(address target); error ConnectorNotSet(address target); error ArrayLengthMismatch(); ICustomConnectorRegistry[] public customRegistries; mapping(address target => address connector) private connectors_; constructor( address admin_, address timelockAdmin_ ) Admin(admin_) TimelockAdmin(timelockAdmin_) { } /// Admin functions /// @notice Update connector addresses for a batch of targets. /// @dev Controls which connector contracts are used for the specified /// targets. /// @custom:access Restricted to protocol admin. function setConnectors( address[] calldata targets, address[] calldata connectors ) external onlyAdmin { if (targets.length != connectors.length) { revert ArrayLengthMismatch(); } for (uint256 i; i != targets.length;) { if (connectors_[targets[i]] != address(0)) { revert ConnectorAlreadySet(targets[i]); } connectors_[targets[i]] = connectors[i]; emit ConnectorChanged(targets[i], connectors[i]); unchecked { ++i; } } } function updateConnectors( address[] calldata targets, address[] calldata connectors ) external onlyTimelockAdmin { if (targets.length != connectors.length) { revert ArrayLengthMismatch(); } for (uint256 i; i != targets.length;) { if (connectors_[targets[i]] == address(0)) { revert ConnectorNotSet(targets[i]); } connectors_[targets[i]] = connectors[i]; emit ConnectorChanged(targets[i], connectors[i]); unchecked { ++i; } } } /// @notice Append an address to the custom registries list. /// @custom:access Restricted to protocol admin. function addCustomRegistry( ICustomConnectorRegistry registry ) external onlyAdmin { if (isCustomRegistry(registry)) { revert CustomRegistryAlreadyRegistered(); } customRegistries.push(registry); emit CustomRegistryAdded(address(registry)); } /// @notice Replace an address in the custom registries list. /// @custom:access Restricted to protocol admin. function updateCustomRegistry( uint256 index, ICustomConnectorRegistry newRegistry ) external onlyTimelockAdmin { ICustomConnectorRegistry oldRegistry = customRegistries[index]; emit CustomRegistryRemoved(address(oldRegistry)); customRegistries[index] = newRegistry; if (address(newRegistry) != address(0)) { emit CustomRegistryAdded(address(newRegistry)); } } /// Public functions function connectorOf( address target ) external view returns (address) { address connector = _getConnector(target); if (connector != address(0)) { return connector; } revert ConnectorNotRegistered(target); } function hasConnector( address target ) external view returns (bool) { return _getConnector(target) != address(0); } function isCustomRegistry( ICustomConnectorRegistry registry ) public view returns (bool) { for (uint256 i; i != customRegistries.length;) { if (address(customRegistries[i]) == address(registry)) { return true; } unchecked { ++i; } } return false; } /// Internal functions function _getConnector( address target ) internal view returns (address) { address connector = connectors_[target]; if (connector != address(0)) { return connector; } uint256 length = customRegistries.length; for (uint256 i; i != length;) { if (address(customRegistries[i]) != address(0)) { (bool success, bytes memory data) = address(customRegistries[i]) .staticcall( abi.encodeWithSelector( ICustomConnectorRegistry.connectorOf.selector, target ) ); if (success && data.length == 32) { address _connector = abi.decode(data, (address)); if (_connector != address(0)) { return _connector; } } } unchecked { ++i; } } return address(0); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /// @title TimelockAdmin contract /// @author vfat.tools /// @notice Provides an timelockAdministration mechanism allowing restricted /// functions abstract contract TimelockAdmin { /// ERRORS /// /// @notice Thrown when the caller is not the timelockAdmin error NotTimelockAdminError(); /// EVENTS /// /// @notice Emitted when a new timelockAdmin is set /// @param oldTimelockAdmin Address of the old timelockAdmin /// @param newTimelockAdmin Address of the new timelockAdmin event TimelockAdminSet(address oldTimelockAdmin, address newTimelockAdmin); /// STORAGE /// /// @notice Address of the current timelockAdmin address public timelockAdmin; /// MODIFIERS /// /// @dev Restricts a function to the timelockAdmin modifier onlyTimelockAdmin() { if (msg.sender != timelockAdmin) revert NotTimelockAdminError(); _; } /// WRITE FUNCTIONS /// /// @param timelockAdmin_ Address of the timelockAdmin constructor( address timelockAdmin_ ) { emit TimelockAdminSet(timelockAdmin, timelockAdmin_); timelockAdmin = timelockAdmin_; } /// @notice Sets a new timelockAdmin /// @dev Can only be called by the current timelockAdmin /// @param newTimelockAdmin Address of the new timelockAdmin function setTimelockAdmin( address newTimelockAdmin ) external onlyTimelockAdmin { emit TimelockAdminSet(timelockAdmin, newTimelockAdmin); timelockAdmin = newTimelockAdmin; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol"; import { SwapParams } from "contracts/structs/SwapStructs.sol"; struct Farm { address stakingContract; uint256 poolIndex; } struct DepositParams { Farm farm; address[] tokensIn; uint256[] amountsIn; ZapIn zap; bytes extraData; } struct WithdrawParams { bytes extraData; ZapOut zap; address[] tokensOut; } struct HarvestParams { SwapParams[] swaps; bytes extraData; address[] tokensOut; } struct CompoundParams { Farm claimFarm; bytes claimExtraData; address[] rewardTokens; ZapIn zap; Farm depositFarm; bytes depositExtraData; } struct SimpleDepositParams { Farm farm; address lpToken; uint256 amountIn; bytes extraData; } struct SimpleHarvestParams { address[] rewardTokens; bytes extraData; } struct SimpleWithdrawParams { address lpToken; uint256 amountOut; bytes extraData; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Sickle } from "contracts/Sickle.sol"; struct PositionKey { Sickle sickle; address stakingContract; uint256 poolIndex; } enum RewardBehavior { None, Harvest, Compound } struct RewardConfig { RewardBehavior rewardBehavior; address harvestTokenOut; } struct ExitConfig { uint256 baseTokenIndex; uint256 quoteTokenIndex; uint256 triggerPriceLow; address exitTokenOutLow; uint256 triggerPriceHigh; address exitTokenOutHigh; uint256[] triggerReservesLow; address[] triggerReservesTokensOut; uint256 priceImpactBP; uint256 slippageBP; } /** * Settings for automating an ERC20 position * @param pool: Uniswap or Aerodrome vAMM/sAMM pair for the position (requires * ILiquidityConnector connector registered) * @param router: Router for the pair (requires connector registration) * @param automateRewards: Whether to automatically harvest or compound rewards * for this position, regardless of rebalance settings. * @param rewardConfig: Configuration for reward automation * Harvest as-is, harvest and convert to a different token, or compound into the * position. * @param autoExit: Whether to automatically exit the position when it goes out * of * range * @param exitConfig: Configuration for the above */ struct PositionSettings { address pool; address router; bool automateRewards; RewardConfig rewardConfig; bool autoExit; ExitConfig exitConfig; bytes extraData; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { AddLiquidityParams, RemoveLiquidityParams } from "contracts/structs/LiquidityStructs.sol"; interface ILiquidityConnector { error InvalidPrice(); function addLiquidity( AddLiquidityParams memory addLiquidityParams ) external payable; function removeLiquidity( RemoveLiquidityParams memory removeLiquidityParams ) external; function getPoolPrice( address lpToken, uint256 baseTokenIndex, uint256 quoteTokenIndex ) external view returns (uint256); function getReserves( address lpToken ) external view returns (uint256[] memory reserves); function getTokens( address lpToken ) external view returns (address[] memory tokens); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { PositionKey, PositionSettings } from "contracts/structs/PositionSettingsStructs.sol"; interface IPositionSettingsRegistry { error InvalidStakingContract(); error InvalidPool(); error InvalidRouter(); error SickleNotDeployed(); error AutoHarvestNotSet(); error AutoCompoundNotSet(); error RewardBehaviorNotSet(); error AutoExitNotSet(); error ConditionsNotMet(); error InvalidPrice(); error InvalidTokenOut(); error ExitTriggersNotSet(); error InvalidSlippageBP(); error InvalidPriceImpactBP(); error OnlySickle(); error NonZeroRewardConfig(); error NonZeroExitConfig(); error InvalidTriggerReserves(); error InvalidTokenIndices(); error InvalidExitTriggers(); event PositionSettingsSet(PositionKey key, PositionSettings settings); event ConnectionRegistrySet(address connectorRegistry); function getPositionSettings( PositionKey calldata key ) external view returns (PositionSettings memory); function setPositionSettings( PositionKey calldata key, PositionSettings calldata settings ) external; function validateExitFor( PositionKey memory key ) external; function validateHarvestFor( PositionKey memory key ) external; function validateCompoundFor( PositionKey memory key ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; library SickleStorageEvents { event ApprovedAddressChanged(address newApproved); } /// @title SickleStorage contract /// @author vfat.tools /// @notice Base storage of the Sickle contract /// @dev This contract needs to be inherited by stub contracts meant to be used /// with `delegatecall` abstract contract SickleStorage is Initializable { /// ERRORS /// /// @notice Thrown when the caller is not the owner of the Sickle contract error NotOwnerError(); // 0x74a21527 /// @notice Thrown when the caller is not a strategy contract or the /// Flashloan Stub error NotStrategyError(); // 0x4581ba62 /// STORAGE /// /// @notice Address of the owner address public owner; /// @notice An address that can be set by the owner of the Sickle contract /// in order to trigger specific functions. address public approved; /// MODIFIERS /// /// @dev Restricts a function call to the owner of the Sickle contract modifier onlyOwner() { if (msg.sender != owner) revert NotOwnerError(); _; } /// INITIALIZATION /// /// @param owner_ Address of the owner of this Sickle contract function _initializeSickleStorage( address owner_, address approved_ ) internal onlyInitializing { owner = owner_; approved = approved_; } /// WRITE FUNCTIONS /// /// @notice Sets the approved address of this Sickle /// @param newApproved Address meant to be approved by the owner function setApproved( address newApproved ) external onlyOwner { approved = newApproved; emit SickleStorageEvents.ApprovedAddressChanged(newApproved); } /// @notice Checks if `caller` is either the owner of the Sickle contract /// or was approved by them /// @param caller Address to check /// @return True if `caller` is either the owner of the Sickle contract function isOwnerOrApproved( address caller ) public view returns (bool) { return caller == owner || caller == approved; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { SickleRegistry } from "contracts/SickleRegistry.sol"; /// @title Multicall contract /// @author vfat.tools /// @notice Enables calling multiple methods in a single call to the contract abstract contract Multicall { /// ERRORS /// error MulticallParamsMismatchError(); // 0xc1e637c9 /// @notice Thrown when the target contract is not whitelisted /// @param target Address of the non-whitelisted target error TargetNotWhitelisted(address target); // 0x47ccabe7 /// @notice Thrown when the caller is not whitelisted /// @param caller Address of the non-whitelisted caller error CallerNotWhitelisted(address caller); // 0x252c8273 /// STORAGE /// /// @notice Address of the SickleRegistry contract /// @dev Needs to be immutable so that it's accessible for Sickle proxies SickleRegistry public immutable registry; /// INITIALIZATION /// /// @param registry_ Address of the SickleRegistry contract constructor( SickleRegistry registry_ ) { registry = registry_; } /// WRITE FUNCTIONS /// /// @notice Batch multiple calls together (calls or delegatecalls) /// @param targets Array of targets to call /// @param data Array of data to pass with the calls function multicall( address[] calldata targets, bytes[] calldata data ) external payable { if (targets.length != data.length) { revert MulticallParamsMismatchError(); } if (!registry.isWhitelistedCaller(msg.sender)) { revert CallerNotWhitelisted(msg.sender); } for (uint256 i = 0; i != data.length;) { if (targets[i] == address(0)) { unchecked { ++i; } continue; // No-op } if (targets[i] != address(this)) { if (!registry.isWhitelistedTarget(targets[i])) { revert TargetNotWhitelisted(targets[i]); } } (bool success, bytes memory result) = targets[i].delegatecall(data[i]); if (!success) { if (result.length == 0) revert(); assembly { revert(add(32, result), mload(result)) } } unchecked { ++i; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Admin } from "contracts/base/Admin.sol"; library SickleRegistryEvents { event CollectorChanged(address newCollector); event FeesUpdated(bytes32[] feeHashes, uint256[] feesInBP); event ReferralCodeCreated(bytes32 indexed code, address indexed referrer); // Multicall caller and target whitelist status changes event CallerStatusChanged(address caller, bool isWhitelisted); event TargetStatusChanged(address target, bool isWhitelisted); } /// @title SickleRegistry contract /// @author vfat.tools /// @notice Manages the whitelisted contracts and the collector address contract SickleRegistry is Admin { /// CONSTANTS /// uint256 constant MAX_FEE = 500; // 5% /// ERRORS /// error ArrayLengthMismatch(); // 0xa24a13a6 error FeeAboveMaxLimit(); // 0xd6cf7b5e error InvalidReferralCode(); // 0xe55b4629 /// STORAGE /// /// @notice Address of the fee collector address public collector; /// @notice Tracks the contracts that can be called through Sickle multicall /// @return True if the contract is a whitelisted target mapping(address => bool) public isWhitelistedTarget; /// @notice Tracks the contracts that can call Sickle multicall /// @return True if the contract is a whitelisted caller mapping(address => bool) public isWhitelistedCaller; /// @notice Keeps track of the referrers and their associated code mapping(bytes32 => address) public referralCodes; /// @notice Mapping for fee hashes (hash of the strategy contract addresses /// and the function selectors) and their associated fees /// @return The fee in basis points to apply to the transaction amount mapping(bytes32 => uint256) public feeRegistry; /// WRITE FUNCTIONS /// /// @param admin_ Address of the admin /// @param collector_ Address of the collector constructor(address admin_, address collector_) Admin(admin_) { collector = collector_; } /// @notice Updates the whitelist status for multiple multicall targets /// @param targets Addresses of the contracts to update /// @param isApproved New status for the contracts /// @custom:access Restricted to protocol admin. function setWhitelistedTargets( address[] calldata targets, bool isApproved ) external onlyAdmin { for (uint256 i; i < targets.length;) { isWhitelistedTarget[targets[i]] = isApproved; emit SickleRegistryEvents.TargetStatusChanged( targets[i], isApproved ); unchecked { ++i; } } } /// @notice Updates the fee collector address /// @param newCollector Address of the new fee collector /// @custom:access Restricted to protocol admin. function updateCollector( address newCollector ) external onlyAdmin { collector = newCollector; emit SickleRegistryEvents.CollectorChanged(newCollector); } /// @notice Update the whitelist status for multiple multicall callers /// @param callers Addresses of the callers /// @param isApproved New status for the caller /// @custom:access Restricted to protocol admin. function setWhitelistedCallers( address[] calldata callers, bool isApproved ) external onlyAdmin { for (uint256 i; i < callers.length;) { isWhitelistedCaller[callers[i]] = isApproved; emit SickleRegistryEvents.CallerStatusChanged( callers[i], isApproved ); unchecked { ++i; } } } /// @notice Associates a referral code to the address of the caller function setReferralCode( bytes32 referralCode ) external { if (referralCodes[referralCode] != address(0)) { revert InvalidReferralCode(); } referralCodes[referralCode] = msg.sender; emit SickleRegistryEvents.ReferralCodeCreated(referralCode, msg.sender); } /// @notice Update the fees for multiple strategy functions /// @param feeHashes Array of fee hashes /// @param feesArray Array of fees to apply (in basis points) /// @custom:access Restricted to protocol admin. function setFees( bytes32[] calldata feeHashes, uint256[] calldata feesArray ) external onlyAdmin { if (feeHashes.length != feesArray.length) { revert ArrayLengthMismatch(); } for (uint256 i = 0; i < feeHashes.length;) { if (feesArray[i] <= MAX_FEE) { feeRegistry[feeHashes[i]] = feesArray[i]; } else { revert FeeAboveMaxLimit(); } unchecked { ++i; } } emit SickleRegistryEvents.FeesUpdated(feeHashes, feesArray); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/Clones.sol) pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(0, 0x09, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(0, 0x09, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := keccak256(add(ptr, 0x43), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /// @title Admin contract /// @author vfat.tools /// @notice Provides an administration mechanism allowing restricted functions abstract contract Admin { /// ERRORS /// /// @notice Thrown when the caller is not the admin error NotAdminError(); //0xb5c42b3b /// EVENTS /// /// @notice Emitted when a new admin is set /// @param oldAdmin Address of the old admin /// @param newAdmin Address of the new admin event AdminSet(address oldAdmin, address newAdmin); /// STORAGE /// /// @notice Address of the current admin address public admin; /// MODIFIERS /// /// @dev Restricts a function to the admin modifier onlyAdmin() { if (msg.sender != admin) revert NotAdminError(); _; } /// WRITE FUNCTIONS /// /// @param admin_ Address of the admin constructor( address admin_ ) { emit AdminSet(address(0), admin_); admin = admin_; } /// @notice Sets a new admin /// @param newAdmin Address of the new admin /// @custom:access Restricted to protocol admin. function setAdmin( address newAdmin ) external onlyAdmin { emit AdminSet(admin, newAdmin); admin = newAdmin; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { SwapParams } from "contracts/structs/SwapStructs.sol"; import { AddLiquidityParams, RemoveLiquidityParams } from "contracts/structs/LiquidityStructs.sol"; struct ZapIn { SwapParams[] swaps; AddLiquidityParams addLiquidityParams; } struct ZapOut { RemoveLiquidityParams removeLiquidityParams; SwapParams[] swaps; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct SwapParams { address tokenApproval; address router; uint256 amountIn; uint256 desiredAmountOut; uint256 minAmountOut; address tokenIn; address tokenOut; bytes extraData; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct AddLiquidityParams { address router; address lpToken; address[] tokens; uint256[] desiredAmounts; uint256[] minAmounts; bytes extraData; } struct RemoveLiquidityParams { address router; address lpToken; address[] tokens; uint256 lpAmountIn; uint256[] minAmountsOut; bytes extraData; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ 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"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ 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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "solmate/=lib/solmate/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@morpho-blue/=lib/morpho-blue/src/", "ds-test/=lib/solmate/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "morpho-blue/=lib/morpho-blue/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract SickleFactory","name":"_factory","type":"address"},{"internalType":"contract ConnectorRegistry","name":"connectorRegistry","type":"address"},{"internalType":"address","name":"timelockAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AutoCompoundNotSet","type":"error"},{"inputs":[],"name":"AutoExitNotSet","type":"error"},{"inputs":[],"name":"AutoHarvestNotSet","type":"error"},{"inputs":[],"name":"ConditionsNotMet","type":"error"},{"inputs":[],"name":"ExitTriggersNotSet","type":"error"},{"inputs":[],"name":"InvalidExitTriggers","type":"error"},{"inputs":[],"name":"InvalidPool","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidPriceImpactBP","type":"error"},{"inputs":[],"name":"InvalidRouter","type":"error"},{"inputs":[],"name":"InvalidSlippageBP","type":"error"},{"inputs":[],"name":"InvalidStakingContract","type":"error"},{"inputs":[],"name":"InvalidTokenIndices","type":"error"},{"inputs":[],"name":"InvalidTokenOut","type":"error"},{"inputs":[],"name":"InvalidTriggerReserves","type":"error"},{"inputs":[],"name":"NonZeroExitConfig","type":"error"},{"inputs":[],"name":"NonZeroRewardConfig","type":"error"},{"inputs":[],"name":"NotTimelockAdminError","type":"error"},{"inputs":[],"name":"OnlySickle","type":"error"},{"inputs":[],"name":"RewardBehaviorNotSet","type":"error"},{"inputs":[],"name":"SickleNotDeployed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"connectorRegistry","type":"address"}],"name":"ConnectionRegistrySet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"indexed":false,"internalType":"struct PositionKey","name":"key","type":"tuple"},{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bool","name":"automateRewards","type":"bool"},{"components":[{"internalType":"enum RewardBehavior","name":"rewardBehavior","type":"uint8"},{"internalType":"address","name":"harvestTokenOut","type":"address"}],"internalType":"struct RewardConfig","name":"rewardConfig","type":"tuple"},{"internalType":"bool","name":"autoExit","type":"bool"},{"components":[{"internalType":"uint256","name":"baseTokenIndex","type":"uint256"},{"internalType":"uint256","name":"quoteTokenIndex","type":"uint256"},{"internalType":"uint256","name":"triggerPriceLow","type":"uint256"},{"internalType":"address","name":"exitTokenOutLow","type":"address"},{"internalType":"uint256","name":"triggerPriceHigh","type":"uint256"},{"internalType":"address","name":"exitTokenOutHigh","type":"address"},{"internalType":"uint256[]","name":"triggerReservesLow","type":"uint256[]"},{"internalType":"address[]","name":"triggerReservesTokensOut","type":"address[]"},{"internalType":"uint256","name":"priceImpactBP","type":"uint256"},{"internalType":"uint256","name":"slippageBP","type":"uint256"}],"internalType":"struct ExitConfig","name":"exitConfig","type":"tuple"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"indexed":false,"internalType":"struct PositionSettings","name":"settings","type":"tuple"}],"name":"PositionSettingsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldTimelockAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newTimelockAdmin","type":"address"}],"name":"TimelockAdminSet","type":"event"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract SickleFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey","name":"key","type":"tuple"}],"name":"getPositionSettings","outputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bool","name":"automateRewards","type":"bool"},{"components":[{"internalType":"enum RewardBehavior","name":"rewardBehavior","type":"uint8"},{"internalType":"address","name":"harvestTokenOut","type":"address"}],"internalType":"struct RewardConfig","name":"rewardConfig","type":"tuple"},{"internalType":"bool","name":"autoExit","type":"bool"},{"components":[{"internalType":"uint256","name":"baseTokenIndex","type":"uint256"},{"internalType":"uint256","name":"quoteTokenIndex","type":"uint256"},{"internalType":"uint256","name":"triggerPriceLow","type":"uint256"},{"internalType":"address","name":"exitTokenOutLow","type":"address"},{"internalType":"uint256","name":"triggerPriceHigh","type":"uint256"},{"internalType":"address","name":"exitTokenOutHigh","type":"address"},{"internalType":"uint256[]","name":"triggerReservesLow","type":"uint256[]"},{"internalType":"address[]","name":"triggerReservesTokensOut","type":"address[]"},{"internalType":"uint256","name":"priceImpactBP","type":"uint256"},{"internalType":"uint256","name":"slippageBP","type":"uint256"}],"internalType":"struct ExitConfig","name":"exitConfig","type":"tuple"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct PositionSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPreviousSettingsRegistry","name":"previousPositionSettings","type":"address"},{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey[]","name":"keys","type":"tuple[]"}],"name":"migratePositionSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ConnectorRegistry","name":"connectorRegistry","type":"address"}],"name":"setConnectorRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm[]","name":"farms","type":"tuple[]"},{"components":[{"internalType":"enum RewardBehavior","name":"rewardBehavior","type":"uint8"},{"internalType":"address","name":"harvestTokenOut","type":"address"}],"internalType":"struct RewardConfig","name":"rewardConfig","type":"tuple"}],"name":"setMultiplePositionSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bool","name":"automateRewards","type":"bool"},{"components":[{"internalType":"enum RewardBehavior","name":"rewardBehavior","type":"uint8"},{"internalType":"address","name":"harvestTokenOut","type":"address"}],"internalType":"struct RewardConfig","name":"rewardConfig","type":"tuple"},{"internalType":"bool","name":"autoExit","type":"bool"},{"components":[{"internalType":"uint256","name":"baseTokenIndex","type":"uint256"},{"internalType":"uint256","name":"quoteTokenIndex","type":"uint256"},{"internalType":"uint256","name":"triggerPriceLow","type":"uint256"},{"internalType":"address","name":"exitTokenOutLow","type":"address"},{"internalType":"uint256","name":"triggerPriceHigh","type":"uint256"},{"internalType":"address","name":"exitTokenOutHigh","type":"address"},{"internalType":"uint256[]","name":"triggerReservesLow","type":"uint256[]"},{"internalType":"address[]","name":"triggerReservesTokensOut","type":"address[]"},{"internalType":"uint256","name":"priceImpactBP","type":"uint256"},{"internalType":"uint256","name":"slippageBP","type":"uint256"}],"internalType":"struct ExitConfig","name":"exitConfig","type":"tuple"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct PositionSettings","name":"settings","type":"tuple"}],"name":"setPositionSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey","name":"key","type":"tuple"},{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bool","name":"automateRewards","type":"bool"},{"components":[{"internalType":"enum RewardBehavior","name":"rewardBehavior","type":"uint8"},{"internalType":"address","name":"harvestTokenOut","type":"address"}],"internalType":"struct RewardConfig","name":"rewardConfig","type":"tuple"},{"internalType":"bool","name":"autoExit","type":"bool"},{"components":[{"internalType":"uint256","name":"baseTokenIndex","type":"uint256"},{"internalType":"uint256","name":"quoteTokenIndex","type":"uint256"},{"internalType":"uint256","name":"triggerPriceLow","type":"uint256"},{"internalType":"address","name":"exitTokenOutLow","type":"address"},{"internalType":"uint256","name":"triggerPriceHigh","type":"uint256"},{"internalType":"address","name":"exitTokenOutHigh","type":"address"},{"internalType":"uint256[]","name":"triggerReservesLow","type":"uint256[]"},{"internalType":"address[]","name":"triggerReservesTokensOut","type":"address[]"},{"internalType":"uint256","name":"priceImpactBP","type":"uint256"},{"internalType":"uint256","name":"slippageBP","type":"uint256"}],"internalType":"struct ExitConfig","name":"exitConfig","type":"tuple"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct PositionSettings","name":"settings","type":"tuple"}],"name":"setPositionSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTimelockAdmin","type":"address"}],"name":"setTimelockAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelockAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey","name":"key","type":"tuple"}],"name":"validateCompoundFor","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey","name":"key","type":"tuple"}],"name":"validateExitFor","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract Sickle","name":"sickle","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct PositionKey","name":"key","type":"tuple"}],"name":"validateHarvestFor","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620032b6380380620032b6833981016040819052620000349162000106565b600054604080516001600160a01b039283168152918316602083015282917f6502ca129870a6ac685369c8428164757ede26f9a492bf9ae7eac4abc0c49fcf910160405180910390a1600080546001600160a01b03199081166001600160a01b03938416179091558482166080526001805490911691841691821790556040519081527f49ff6f7f9fa2954ed0f7b0b88e2b7297bb2168aa74304ab0a6807dae1fd29c4a9060200160405180910390a15050506200015a565b6001600160a01b03811681146200010357600080fd5b50565b6000806000606084860312156200011c57600080fd5b83516200012981620000ed565b60208501519093506200013c81620000ed565b60408501519092506200014f81620000ed565b809150509250925092565b6080516131396200017d600039600081816101a8015261145f01526131396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063849ef53d11610071578063849ef53d1461014a5780639b6a43771461015d578063a916e1cf14610170578063bca9ca7314610190578063c45a0155146101a3578063f1cf4182146101ca57600080fd5b80631cea795b146100b95780633feab9bc146100ce578063459e2684146100e157806364ceb97a146100f45780636aacf4b9146101245780637ac5f2d814610137575b600080fd5b6100cc6100c73660046119cd565b6101dd565b005b6100cc6100dc366004611a7f565b610753565b6100cc6100ef366004611adf565b6109ba565b600054610107906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc610132366004611b02565b610c30565b6100cc610145366004611b4a565b610e75565b6100cc610158366004611b4a565b610f09565b6100cc61016b366004611b67565b610f88565b61018361017e366004611adf565b6110f7565b60405161011b9190611e1e565b6100cc61019e366004611adf565b611391565b6101077f000000000000000000000000000000000000000000000000000000000000000081565b6100cc6101d8366004611adf565b6113e8565b60006101e83361143b565b905060005b8281101561074c57816001600160a01b031684848381811061021157610211611e31565b6102279260206060909202019081019150611b4a565b6001600160a01b03161461024e5760405163b91a09e760e01b815260040160405180910390fd5b6000856001600160a01b031663a916e1cf86868581811061027157610271611e31565b9050606002016040518263ffffffff1660e01b81526004016102939190611e7f565b6101c060405180830381865afa1580156102b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d59190612035565b905060006040518060e0016040528083600001516001600160a01b0316815260200183602001516001600160a01b031681526020018360400151151581526020018360600151815260200183608001511515815260200160405180610140016040528060008152602001600181526020018560a001516020015181526020018560a00151608001516001600160a01b031681526020018560a001516000015181526020018560a0015160a001516001600160a01b0316815260200160026001600160401b038111156103a9576103a9611e8d565b6040519080825280602002602001820160405280156103d2578160200160208202803683370190505b50815260408051600280825260608201835260209384019391929091830190803683370190505081526020018560a0015160c0015181526020018560a0015160e0015181525081526020016040518060200160405280600081525081525090508160a00151604001518160a0015160c0015160008151811061045657610456611e31565b6020026020010181815250508160a00151606001518160a0015160c0015160018151811061048657610486611e31565b6020026020010181815250508160a00151608001518160a0015160e001516000815181106104b6576104b6611e31565b60200260200101906001600160a01b031690816001600160a01b0316815250508160a0015160a001518160a0015160e001516001815181106104fa576104fa611e31565b60200260200101906001600160a01b031690816001600160a01b031681525050600086868581811061052e5761052e611e31565b9050606002016040516020016105449190611e7f565b60408051808303601f1901815291815281516020928301206000818152600280855290839020865181546001600160a01b0319166001600160a01b039182161782559487015160018083018054968a0151929097166001600160a81b031990961695909517600160a01b9115159190910217909455606086015180518583018054949750889695929490939192849260ff199092169184908111156105eb576105eb611beb565b02179055506020918201518154610100600160a81b0319166101006001600160a01b03928316021790915560808481015160038501805460ff191691151591909117905560a0808601518051600487019081558186015160058801556040820151600688015560608201516007880180546001600160a01b03199081169288169290921790559382015160088801559181015160098701805490941694169390931790915560c08201518051929391926106ab92600a870192019061184f565b5060e082015180516106c791600784019160209091019061189a565b5061010082015160088201556101209091015160099091015560c0820151600e8201906106f49082612179565b509050506000805160206130e483398151915287878681811061071957610719611e31565b9050606002018360405161072e92919061223c565b60405180910390a1505050808061074490612264565b9150506101ed565b5050505050565b6107606020830183611b4a565b6107698261250a565b6001600160a01b038216610790576040516307b18df360e31b815260040160405180910390fd5b8060400151156107ac576107a781606001516114f9565b610800565b600060608201515160028111156107c5576107c5611beb565b1415806107e257506060810151602001516001600160a01b031615155b15610800576040516356564be760e11b815260040160405180910390fd5b806080015115610818576108138161157a565b6108f7565b60a08101516040015115158061083e575060a0810151606001516001600160a01b031615155b80610850575060a08101516080015115155b8061086a575060a08082015101516001600160a01b031615155b8061087d575060a0810151610120015115155b80610890575060a0810151610100015115155b806108a4575060008160a0015160c0015151115b806108b8575060008160a0015160e0015151115b806108c7575060a08101515115155b806108d9575060a08101516020015115155b156108f75760405163204178bd60e01b815260040160405180910390fd5b6000604051806060016040528061090d3361143b565b6001600160a01b0316815260209081019061092a90880188611b4a565b6001600160a01b031681526020018660200135815250905060008160405160200161095591906125f4565b60408051601f198184030181529181528151602092830120600081815260029093529120909150859061098882826129bc565b9050506000805160206130e483398151915282866040516109aa929190612d65565b60405180910390a1505050505050565b60006109c5826110f7565b60a08101516080820151919250906109f0576040516301d7fb3960e01b815260040160405180910390fd5b60015460208301516040516363cd755760e11b81526001600160a01b039182166004820152600092919091169063c79aeaae90602401602060405180830381865afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190612d85565b8351835160208501516040516307283b8360e31b81526001600160a01b0393841660048201526024810192909252604482015291925060009190831690633941dc1890606401602060405180830381865afa158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee9190612da2565b6040840151608085015160c086015151929350908310919083119060009015610bf2578651604051630fa6707960e21b81526001600160a01b039182166004820152600091871690633e99c1e490602401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612dbb565b905060005b8760c0015151811015610bef578760c001518181518110610bac57610bac611e31565b6020026020010151828281518110610bc657610bc6611e31565b60200260200101511015610bdd5760019250610bef565b80610be781612264565b915050610b89565b50505b82158015610bfe575081155b8015610c08575080155b15610c265760405163126d58d760e31b815260040160405180910390fd5b5050505050505050565b610c406040830160208401611b4a565b610c498261250a565b6001600160a01b038216610c70576040516307b18df360e31b815260040160405180910390fd5b806040015115610c8c57610c8781606001516114f9565b610ce0565b60006060820151516002811115610ca557610ca5611beb565b141580610cc257506060810151602001516001600160a01b031615155b15610ce0576040516356564be760e11b815260040160405180910390fd5b806080015115610cf857610cf38161157a565b610dd7565b60a081015160400151151580610d1e575060a0810151606001516001600160a01b031615155b80610d30575060a08101516080015115155b80610d4a575060a08082015101516001600160a01b031615155b80610d5d575060a0810151610120015115155b80610d70575060a0810151610100015115155b80610d84575060008160a0015160c0015151115b80610d98575060008160a0015160e0015151115b80610da7575060a08101515115155b80610db9575060a08101516020015115155b15610dd75760405163204178bd60e01b815260040160405180910390fd5b3380610de66020870187611b4a565b6001600160a01b031614610e0d5760405163b91a09e760e01b815260040160405180910390fd5b600085604051602001610e209190611e7f565b60408051601f1981840301815291815281516020928301206000818152600290935291209091508590610e5382826129bc565b9050506000805160206130e483398151915286866040516109aa929190612e4b565b6000546001600160a01b03163314610ea0576040516347323cef60e01b815260040160405180910390fd5b600054604080516001600160a01b03928316815291831660208301527f6502ca129870a6ac685369c8428164757ede26f9a492bf9ae7eac4abc0c49fcf910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f34576040516347323cef60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f49ff6f7f9fa2954ed0f7b0b88e2b7297bb2168aa74304ab0a6807dae1fd29c4a9060200160405180910390a150565b610f9736829003820182612e55565b610fa0816114f9565b6000610fab3361143b565b604080516060810182526000808252602082018190529181018290529192505b858110156110ee576040518060600160405280846001600160a01b03168152602001888884818110610fff57610fff611e31565b6110159260206040909202019081019150611b4a565b6001600160a01b0316815260200188888481811061103557611035611e31565b90506040020160200135815250915060008260405160200161105791906125f4565b60408051601f19818403018152918152815160209283012060008181526002938490529190912060018101805460ff60a01b1916600160a01b1790559092508791016110a3828261263c565b50506000818152600260205260409081902090516000805160206130e4833981519152916110d39186919061302d565b60405180910390a150806110e681612264565b915050610fcb565b50505050505050565b6110ff6118ef565b6000826040516020016111129190611e7f565b60408051601f198184030181528282528051602091820120600081815260028084529084902060e08601855280546001600160a01b03908116875260018201549081169487019490945260ff600160a01b909404841615158686015284518086019095528082018054939750909460608701949093919284929091169081111561119e5761119e611beb565b60028111156111af576111af611beb565b815290546001600160a01b036101009091048116602092830152918352600384015460ff161515838201526040805161014081018252600486018054825260058701548285015260068701548284015260078701548516606083015260088701546080830152600987015490941660a0820152600a860180548351818602810186018552818152939096019591949360c0860193929083018282801561127457602002820191906000526020600020905b815481526020019060010190808311611260575b50505050508152602001600782018054806020026020016040519081016040528092919081815260200182805480156112d657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112b8575b50505050508152602001600882015481526020016009820154815250508152602001600e82018054611307906120f7565b80601f0160208091040260200160405190810160405280929190818152602001828054611333906120f7565b80156113805780601f1061135557610100808354040283529160200191611380565b820191906000526020600020905b81548152906001019060200180831161136357829003601f168201915b505050505081525050915050919050565b600061139c826110f7565b9050806040015115806113c65750600160608201515160028111156113c3576113c3611beb565b14155b156113e457604051630839792d60e41b815260040160405180910390fd5b5050565b60006113f3826110f7565b90508060400151158061141d57506002606082015151600281111561141a5761141a611beb565b14155b156113e4576040516311447fdd60e11b815260040160405180910390fd5b6040516312cfc9b560e31b81526001600160a01b03828116600483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063967e4da890602401602060405180830381865afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca9190612d85565b90506001600160a01b0381166114f357604051633098a45560e01b815260040160405180910390fd5b92915050565b60008151600281111561150e5761150e611beb565b0361152c576040516306ea881b60e51b815260040160405180910390fd5b60028151600281111561154157611541611beb565b14801561155a575060208101516001600160a01b031615155b156115775760405162db68fd60e51b815260040160405180910390fd5b50565b80516001600160a01b03166115a15760405162820f3560e61b815260040160405180910390fd5b60208101516001600160a01b03166115cc5760405163466d7fef60e01b815260040160405180910390fd5b60a0810151604001511580156115e8575060a081015160800151155b1561160657604051631463731360e21b815260040160405180910390fd5b60a0810151608081015160409091015110611634576040516301b08de360e01b815260040160405180910390fd5b6101f48160a001516101200151111561166057604051636703cded60e01b815260040160405180910390fd5b6113888160a0015161010001511180611680575060a08101516101000151155b1561169e576040516330223ae760e11b815260040160405180910390fd5b60a081015160e08101515160c09091015151146116ce57604051630204277360e11b815260040160405180910390fd5b60015460208201516040516363cd755760e11b81526001600160a01b039182166004820152600092919091169063c79aeaae90602401602060405180830381865afa158015611721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117459190612d85565b8251604051630fa6707960e21b81526001600160a01b03918216600482015291925060009190831690633e99c1e490602401600060405180830381865afa158015611794573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117bc9190810190612dbb565b905080518360a00151600001511015806117df575080518360a001516020015110155b806117f3575060a083015160208101519051145b156118115760405163a09eec5960e01b815260040160405180910390fd5b60a083015160c00151511561184a578260a0015160c001515181511461184a57604051630204277360e11b815260040160405180910390fd5b505050565b82805482825590600052602060002090810192821561188a579160200282015b8281111561188a57825182559160200191906001019061186f565b506118969291506119a3565b5090565b82805482825590600052602060002090810192821561188a579160200282015b8281111561188a57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906118ba565b6040805160e081018252600080825260208083018290528284018290528351808501909452818452830152906060820190815260200160001515815260200161199660405180610140016040528060008152602001600081526020016000815260200160006001600160a01b031681526020016000815260200160006001600160a01b03168152602001606081526020016060815260200160008152602001600081525090565b8152602001606081525090565b5b8082111561189657600081556001016119a4565b6001600160a01b038116811461157757600080fd5b6000806000604084860312156119e257600080fd5b83356119ed816119b8565b925060208401356001600160401b0380821115611a0957600080fd5b818601915086601f830112611a1d57600080fd5b813581811115611a2c57600080fd5b876020606083028501011115611a4157600080fd5b6020830194508093505050509250925092565b600060408284031215611a6657600080fd5b50919050565b60006101008284031215611a6657600080fd5b60008060608385031215611a9257600080fd5b611a9c8484611a54565b915060408301356001600160401b03811115611ab757600080fd5b611ac385828601611a6c565b9150509250929050565b600060608284031215611a6657600080fd5b600060608284031215611af157600080fd5b611afb8383611acd565b9392505050565b60008060808385031215611b1557600080fd5b611b1f8484611acd565b915060608301356001600160401b03811115611ab757600080fd5b8035611b45816119b8565b919050565b600060208284031215611b5c57600080fd5b8135611afb816119b8565b600080600060608486031215611b7c57600080fd5b83356001600160401b0380821115611b9357600080fd5b818601915086601f830112611ba757600080fd5b813581811115611bb657600080fd5b8760208260061b8501011115611bcb57600080fd5b602092830195509350611be2918791508601611a54565b90509250925092565b634e487b7160e01b600052602160045260246000fd5b60038110611c1f57634e487b7160e01b600052602160045260246000fd5b9052565b600081518084526020808501945080840160005b83811015611c5357815187529582019590820190600101611c37565b509495945050505050565b600081518084526020808501945080840160005b83811015611c535781516001600160a01b031687529582019590820190600101611c72565b60006101408251845260208301516020850152604083015160408501526060830151611cce60608601826001600160a01b03169052565b506080830151608085015260a0830151611cf360a08601826001600160a01b03169052565b5060c08301518160c0860152611d0b82860182611c23565b91505060e083015184820360e0860152611d258282611c5e565b6101008581015190870152610120948501519490950193909352509192915050565b6000815180845260005b81811015611d6d57602081850181015186830182015201611d51565b506000602082860101526020601f19601f83011685010191505092915050565b600061010060018060a01b038084511685528060208501511660208601526040840151151560408601526060840151611dca606087018251611c01565b602001511660808581019190915283015180151560a08601525060a08301518160c0860152611dfb82860182611c97565b91505060c083015184820360e0860152611e158282611d47565b95945050505050565b602081526000611afb6020830184611d8d565b634e487b7160e01b600052603260045260246000fd5b8035611e52816119b8565b6001600160a01b039081168352602082013590611e6e826119b8565b166020830152604090810135910152565b606081016114f38284611e47565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715611ec557611ec5611e8d565b60405290565b604080519081016001600160401b0381118282101715611ec557611ec5611e8d565b60405161014081016001600160401b0381118282101715611ec557611ec5611e8d565b60405160e081016001600160401b0381118282101715611ec557611ec5611e8d565b604051601f8201601f191681016001600160401b0381118282101715611f5a57611f5a611e8d565b604052919050565b8051611b45816119b8565b801515811461157757600080fd5b8051611b4581611f6d565b6003811061157757600080fd5b6000610100808385031215611fa757600080fd5b604051908101906001600160401b0382118183101715611fc957611fc9611e8d565b816040528092508351815260208401516020820152604084015160408201526060840151606082015260808401519150612002826119b8565b81608082015261201460a08501611f62565b60a082015260c084015160c082015260e084015160e0820152505092915050565b60008183036101c081121561204957600080fd5b612051611ea3565b835161205c816119b8565b8152602084015161206c816119b8565b6020820152604084015161207f81611f6d565b806040830152506040605f198301121561209857600080fd5b6120a0611ecb565b915060608401516120b081611f86565b825260808401516120c0816119b8565b6020830152606081018290526120d860a08501611f7b565b60808201526120ea8560c08601611f93565b60a0820152949350505050565b600181811c9082168061210b57607f821691505b602082108103611a6657634e487b7160e01b600052602260045260246000fd5b5b818110156113e4576000815560010161212c565b601f82111561184a57806000526020600020601f840160051c810160208510156121675750805b61074c601f850160051c83018261212b565b81516001600160401b0381111561219257612192611e8d565b6121a6816121a084546120f7565b84612140565b602080601f8311600181146121db57600084156121c35750858301515b600019600386901b1c1916600185901b178555612234565b600085815260208120601f198616915b8281101561220a578886015182559484019460019091019084016121eb565b50858210156122285787850151600019600388901b60f8161c191681555b505060018460011b0185555b505050505050565b6122468184611e47565b60806060820152600061225c6080830184611d8d565b949350505050565b60006001820161228457634e487b7160e01b600052601160045260246000fd5b5060010190565b8035611b4581611f6d565b6000604082840312156122a857600080fd5b6122b0611ecb565b905081356122bd81611f86565b815260208201356122cd816119b8565b602082015292915050565b60006001600160401b038211156122f1576122f1611e8d565b5060051b60200190565b600082601f83011261230c57600080fd5b8135602061232161231c836122d8565b611f32565b82815260059290921b8401810191818101908684111561234057600080fd5b8286015b8481101561235b5780358352918301918301612344565b509695505050505050565b600082601f83011261237757600080fd5b8135602061238761231c836122d8565b82815260059290921b840181019181810190868411156123a657600080fd5b8286015b8481101561235b5780356123bd816119b8565b83529183019183016123aa565b600061014082840312156123dd57600080fd5b6123e5611eed565b905081358152602082013560208201526040820135604082015261240b60608301611b3a565b60608201526080820135608082015261242660a08301611b3a565b60a082015260c08201356001600160401b038082111561244557600080fd5b612451858386016122fb565b60c084015260e084013591508082111561246a57600080fd5b5061247784828501612366565b60e08301525061010080830135818301525061012080830135818301525092915050565b600082601f8301126124ac57600080fd5b81356001600160401b038111156124c5576124c5611e8d565b6124d8601f8201601f1916602001611f32565b8181528460208386010111156124ed57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610100823603121561251d57600080fd5b612525611f10565b61252e83611b3a565b815261253c60208401611b3a565b602082015261254d6040840161228b565b604082015261255f3660608501612296565b606082015261257060a0840161228b565b608082015260c08301356001600160401b038082111561258f57600080fd5b61259b368387016123ca565b60a084015260e08501359150808211156125b457600080fd5b506125c13682860161249b565b60c08301525092915050565b80516001600160a01b03908116835260208083015190911690830152604090810151910152565b606081016114f382846125cd565b600081356114f3816119b8565b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081356114f381611f6d565b813561264781611f86565b6003811061266557634e487b7160e01b600052602160045260246000fd5b815460ff821691508160ff1982161783556020840135612684816119b8565b6001600160a81b03199190911690911760089190911b610100600160a81b031617905550565b6000823561013e198336030181126126c157600080fd5b9190910192915050565b6000808335601e198436030181126126e257600080fd5b8301803591506001600160401b038211156126fc57600080fd5b6020019150600581901b360382131561271457600080fd5b9250929050565b8183101561184a5780600052602060002061273a83820185830161212b565b50505050565b6001600160401b0383111561275757612757611e8d565b600160401b83111561276b5761276b611e8d565b805483825561277b84828461271b565b50818160005260208060002060005b868110156110ee578335828201559282019260010161278a565b6001600160401b038311156127bb576127bb611e8d565b600160401b8311156127cf576127cf611e8d565b80548382556127df84828461271b565b50818160005260208060002060005b868110156110ee578335612801816119b8565b82820155928201926001016127ee565b81358155602082013560018201556040820135600282015561284161283860608401612602565b6003830161260f565b6080820135600482015561286361285a60a08401612602565b6005830161260f565b61287060c08301836126cb565b61287e818360068601612740565b505061288d60e08301836126cb565b61289b8183600786016127a4565b5050610100820135600882015561012082013560098201555050565b6000808335601e198436030181126128ce57600080fd5b8301803591506001600160401b038211156128e857600080fd5b60200191503681900382131561271457600080fd5b6001600160401b0383111561291457612914611e8d565b6129288361292283546120f7565b83612140565b6000601f84116001811461295c57600085156129445750838201355b600019600387901b1c1916600186901b17835561074c565b600083815260209020601f19861690835b8281101561298d578685013582556020948501946001909201910161296d565b50868210156129aa5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81356129c7816119b8565b6129d1818361260f565b506001810160208301356129e4816119b8565b6129ee818361260f565b5060408301356129fd81611f6d565b815460ff60a01b191690151560a01b60ff60a01b16179055612a25606083016002830161263c565b612a4d612a3460a0840161262f565b6003830160ff1981541660ff8315151681178255505050565b612a66612a5d60c08401846126aa565b60048301612811565b612a7360e08301836128b7565b61273a8183600e86016128fd565b6000823561013e19833603018112612a9857600080fd5b90910192915050565b6000808335601e19843603018112612ab857600080fd5b83016020810192503590506001600160401b03811115612ad757600080fd5b8060051b360382131561271457600080fd5b81835260006001600160fb1b03831115612b0257600080fd5b8260051b80836020870137939093016020019392505050565b8183526000602080850194508260005b85811015611c53578135612b3e816119b8565b6001600160a01b031687529582019590820190600101612b2b565b6000610140823584526020830135602085015260408301356040850152612b8260608401611b3a565b6001600160a01b0316606085015260808381013590850152612ba660a08401611b3a565b6001600160a01b031660a0850152612bc160c0840184612aa1565b8260c0870152612bd48387018284612ae9565b92505050612be560e0840184612aa1565b85830360e0870152612bf8838284612b1b565b610100868101359088015261012095860135959096019490945250929392505050565b6000808335601e19843603018112612c3257600080fd5b83016020810192503590506001600160401b03811115612c5157600080fd5b80360382131561271457600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006101008235612c99816119b8565b6001600160a01b039081168552602084013590612cb5826119b8565b9081166020860152604084013590612ccc82611f6d565b9015156040860152606084013590612ce382611f86565b612cf06060870183611c01565b60808501359150612d00826119b8565b166080850152612d1260a0840161228b565b151560a0850152612d2660c0840184612a81565b8160c0860152612d3882860182612b59565b915050612d4860e0840184612c1b565b85830360e0870152612d5b838284612c60565b9695505050505050565b612d6f81846125cd565b60806060820152600061225c6080830184612c89565b600060208284031215612d9757600080fd5b8151611afb816119b8565b600060208284031215612db457600080fd5b5051919050565b60006020808385031215612dce57600080fd5b82516001600160401b03811115612de457600080fd5b8301601f81018513612df557600080fd5b8051612e0361231c826122d8565b81815260059190911b82018301908381019087831115612e2257600080fd5b928401925b82841015612e4057835182529284019290840190612e27565b979650505050505050565b612d6f8184611e47565b600060408284031215612e6757600080fd5b611afb8383612296565b8054612e808360ff8316611c01565b60081c6001600160a01b03166020929092019190915250565b6000815480845260208085019450836000528060002060005b83811015611c5357815487529582019560019182019101612eb2565b6000815480845260208085019450836000528060002060005b83811015611c535781546001600160a01b031687529582019560019182019101612ee7565b6000610140825484526001830154602085015260028301546040850152612f3d60038401546001600160a01b031690565b6001600160a01b0390811660608601526004840154608086015260058401541660a085015260c08401819052612f7881850160068501612e99565b905083810360e0850152612f8f8160078501612ece565b60088401546101008601526009909301546101209094019390935250919050565b60008154612fbd816120f7565b808552602060018381168015612fda5760018114612ff457613022565b60ff1985168884015283151560051b880183019550613022565b866000528260002060005b8581101561301a5781548a8201860152908301908401612fff565b890184019650505b505050505092915050565b61303781846125cd565b608060608201526130636080820161305684546001600160a01b031690565b6001600160a01b03169052565b60018201546001600160a01b03811660a083015260009061308e60c0840160ff8360a01c1615159052565b5061309f60e0830160028501612e71565b600383015460ff1615156101208301526101006101408301526130c9610180830160048501612f0c565b828103607f1901610160840152611e1581600e8601612fb056fe4a8c7af417003b998fff03e8f8f9b00b591215b23e38ee13eeff768daf60b0e6a26469706673582212205e30b8bb6de282046cc0a134da2ffb898d39a3bbfbdd3abb2fd28cbc836d0d3064736f6c63430008130033000000000000000000000000233d9067677dcf1a161954d45b4c965b9d567168000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c990000000000000000000000007f4b6f10c34470ebddf5e7ab049d8dffb01f8a6f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063849ef53d11610071578063849ef53d1461014a5780639b6a43771461015d578063a916e1cf14610170578063bca9ca7314610190578063c45a0155146101a3578063f1cf4182146101ca57600080fd5b80631cea795b146100b95780633feab9bc146100ce578063459e2684146100e157806364ceb97a146100f45780636aacf4b9146101245780637ac5f2d814610137575b600080fd5b6100cc6100c73660046119cd565b6101dd565b005b6100cc6100dc366004611a7f565b610753565b6100cc6100ef366004611adf565b6109ba565b600054610107906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc610132366004611b02565b610c30565b6100cc610145366004611b4a565b610e75565b6100cc610158366004611b4a565b610f09565b6100cc61016b366004611b67565b610f88565b61018361017e366004611adf565b6110f7565b60405161011b9190611e1e565b6100cc61019e366004611adf565b611391565b6101077f000000000000000000000000233d9067677dcf1a161954d45b4c965b9d56716881565b6100cc6101d8366004611adf565b6113e8565b60006101e83361143b565b905060005b8281101561074c57816001600160a01b031684848381811061021157610211611e31565b6102279260206060909202019081019150611b4a565b6001600160a01b03161461024e5760405163b91a09e760e01b815260040160405180910390fd5b6000856001600160a01b031663a916e1cf86868581811061027157610271611e31565b9050606002016040518263ffffffff1660e01b81526004016102939190611e7f565b6101c060405180830381865afa1580156102b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d59190612035565b905060006040518060e0016040528083600001516001600160a01b0316815260200183602001516001600160a01b031681526020018360400151151581526020018360600151815260200183608001511515815260200160405180610140016040528060008152602001600181526020018560a001516020015181526020018560a00151608001516001600160a01b031681526020018560a001516000015181526020018560a0015160a001516001600160a01b0316815260200160026001600160401b038111156103a9576103a9611e8d565b6040519080825280602002602001820160405280156103d2578160200160208202803683370190505b50815260408051600280825260608201835260209384019391929091830190803683370190505081526020018560a0015160c0015181526020018560a0015160e0015181525081526020016040518060200160405280600081525081525090508160a00151604001518160a0015160c0015160008151811061045657610456611e31565b6020026020010181815250508160a00151606001518160a0015160c0015160018151811061048657610486611e31565b6020026020010181815250508160a00151608001518160a0015160e001516000815181106104b6576104b6611e31565b60200260200101906001600160a01b031690816001600160a01b0316815250508160a0015160a001518160a0015160e001516001815181106104fa576104fa611e31565b60200260200101906001600160a01b031690816001600160a01b031681525050600086868581811061052e5761052e611e31565b9050606002016040516020016105449190611e7f565b60408051808303601f1901815291815281516020928301206000818152600280855290839020865181546001600160a01b0319166001600160a01b039182161782559487015160018083018054968a0151929097166001600160a81b031990961695909517600160a01b9115159190910217909455606086015180518583018054949750889695929490939192849260ff199092169184908111156105eb576105eb611beb565b02179055506020918201518154610100600160a81b0319166101006001600160a01b03928316021790915560808481015160038501805460ff191691151591909117905560a0808601518051600487019081558186015160058801556040820151600688015560608201516007880180546001600160a01b03199081169288169290921790559382015160088801559181015160098701805490941694169390931790915560c08201518051929391926106ab92600a870192019061184f565b5060e082015180516106c791600784019160209091019061189a565b5061010082015160088201556101209091015160099091015560c0820151600e8201906106f49082612179565b509050506000805160206130e483398151915287878681811061071957610719611e31565b9050606002018360405161072e92919061223c565b60405180910390a1505050808061074490612264565b9150506101ed565b5050505050565b6107606020830183611b4a565b6107698261250a565b6001600160a01b038216610790576040516307b18df360e31b815260040160405180910390fd5b8060400151156107ac576107a781606001516114f9565b610800565b600060608201515160028111156107c5576107c5611beb565b1415806107e257506060810151602001516001600160a01b031615155b15610800576040516356564be760e11b815260040160405180910390fd5b806080015115610818576108138161157a565b6108f7565b60a08101516040015115158061083e575060a0810151606001516001600160a01b031615155b80610850575060a08101516080015115155b8061086a575060a08082015101516001600160a01b031615155b8061087d575060a0810151610120015115155b80610890575060a0810151610100015115155b806108a4575060008160a0015160c0015151115b806108b8575060008160a0015160e0015151115b806108c7575060a08101515115155b806108d9575060a08101516020015115155b156108f75760405163204178bd60e01b815260040160405180910390fd5b6000604051806060016040528061090d3361143b565b6001600160a01b0316815260209081019061092a90880188611b4a565b6001600160a01b031681526020018660200135815250905060008160405160200161095591906125f4565b60408051601f198184030181529181528151602092830120600081815260029093529120909150859061098882826129bc565b9050506000805160206130e483398151915282866040516109aa929190612d65565b60405180910390a1505050505050565b60006109c5826110f7565b60a08101516080820151919250906109f0576040516301d7fb3960e01b815260040160405180910390fd5b60015460208301516040516363cd755760e11b81526001600160a01b039182166004820152600092919091169063c79aeaae90602401602060405180830381865afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190612d85565b8351835160208501516040516307283b8360e31b81526001600160a01b0393841660048201526024810192909252604482015291925060009190831690633941dc1890606401602060405180830381865afa158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee9190612da2565b6040840151608085015160c086015151929350908310919083119060009015610bf2578651604051630fa6707960e21b81526001600160a01b039182166004820152600091871690633e99c1e490602401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612dbb565b905060005b8760c0015151811015610bef578760c001518181518110610bac57610bac611e31565b6020026020010151828281518110610bc657610bc6611e31565b60200260200101511015610bdd5760019250610bef565b80610be781612264565b915050610b89565b50505b82158015610bfe575081155b8015610c08575080155b15610c265760405163126d58d760e31b815260040160405180910390fd5b5050505050505050565b610c406040830160208401611b4a565b610c498261250a565b6001600160a01b038216610c70576040516307b18df360e31b815260040160405180910390fd5b806040015115610c8c57610c8781606001516114f9565b610ce0565b60006060820151516002811115610ca557610ca5611beb565b141580610cc257506060810151602001516001600160a01b031615155b15610ce0576040516356564be760e11b815260040160405180910390fd5b806080015115610cf857610cf38161157a565b610dd7565b60a081015160400151151580610d1e575060a0810151606001516001600160a01b031615155b80610d30575060a08101516080015115155b80610d4a575060a08082015101516001600160a01b031615155b80610d5d575060a0810151610120015115155b80610d70575060a0810151610100015115155b80610d84575060008160a0015160c0015151115b80610d98575060008160a0015160e0015151115b80610da7575060a08101515115155b80610db9575060a08101516020015115155b15610dd75760405163204178bd60e01b815260040160405180910390fd5b3380610de66020870187611b4a565b6001600160a01b031614610e0d5760405163b91a09e760e01b815260040160405180910390fd5b600085604051602001610e209190611e7f565b60408051601f1981840301815291815281516020928301206000818152600290935291209091508590610e5382826129bc565b9050506000805160206130e483398151915286866040516109aa929190612e4b565b6000546001600160a01b03163314610ea0576040516347323cef60e01b815260040160405180910390fd5b600054604080516001600160a01b03928316815291831660208301527f6502ca129870a6ac685369c8428164757ede26f9a492bf9ae7eac4abc0c49fcf910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f34576040516347323cef60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f49ff6f7f9fa2954ed0f7b0b88e2b7297bb2168aa74304ab0a6807dae1fd29c4a9060200160405180910390a150565b610f9736829003820182612e55565b610fa0816114f9565b6000610fab3361143b565b604080516060810182526000808252602082018190529181018290529192505b858110156110ee576040518060600160405280846001600160a01b03168152602001888884818110610fff57610fff611e31565b6110159260206040909202019081019150611b4a565b6001600160a01b0316815260200188888481811061103557611035611e31565b90506040020160200135815250915060008260405160200161105791906125f4565b60408051601f19818403018152918152815160209283012060008181526002938490529190912060018101805460ff60a01b1916600160a01b1790559092508791016110a3828261263c565b50506000818152600260205260409081902090516000805160206130e4833981519152916110d39186919061302d565b60405180910390a150806110e681612264565b915050610fcb565b50505050505050565b6110ff6118ef565b6000826040516020016111129190611e7f565b60408051601f198184030181528282528051602091820120600081815260028084529084902060e08601855280546001600160a01b03908116875260018201549081169487019490945260ff600160a01b909404841615158686015284518086019095528082018054939750909460608701949093919284929091169081111561119e5761119e611beb565b60028111156111af576111af611beb565b815290546001600160a01b036101009091048116602092830152918352600384015460ff161515838201526040805161014081018252600486018054825260058701548285015260068701548284015260078701548516606083015260088701546080830152600987015490941660a0820152600a860180548351818602810186018552818152939096019591949360c0860193929083018282801561127457602002820191906000526020600020905b815481526020019060010190808311611260575b50505050508152602001600782018054806020026020016040519081016040528092919081815260200182805480156112d657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112b8575b50505050508152602001600882015481526020016009820154815250508152602001600e82018054611307906120f7565b80601f0160208091040260200160405190810160405280929190818152602001828054611333906120f7565b80156113805780601f1061135557610100808354040283529160200191611380565b820191906000526020600020905b81548152906001019060200180831161136357829003601f168201915b505050505081525050915050919050565b600061139c826110f7565b9050806040015115806113c65750600160608201515160028111156113c3576113c3611beb565b14155b156113e457604051630839792d60e41b815260040160405180910390fd5b5050565b60006113f3826110f7565b90508060400151158061141d57506002606082015151600281111561141a5761141a611beb565b14155b156113e4576040516311447fdd60e11b815260040160405180910390fd5b6040516312cfc9b560e31b81526001600160a01b03828116600483015260009182917f000000000000000000000000233d9067677dcf1a161954d45b4c965b9d567168169063967e4da890602401602060405180830381865afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca9190612d85565b90506001600160a01b0381166114f357604051633098a45560e01b815260040160405180910390fd5b92915050565b60008151600281111561150e5761150e611beb565b0361152c576040516306ea881b60e51b815260040160405180910390fd5b60028151600281111561154157611541611beb565b14801561155a575060208101516001600160a01b031615155b156115775760405162db68fd60e51b815260040160405180910390fd5b50565b80516001600160a01b03166115a15760405162820f3560e61b815260040160405180910390fd5b60208101516001600160a01b03166115cc5760405163466d7fef60e01b815260040160405180910390fd5b60a0810151604001511580156115e8575060a081015160800151155b1561160657604051631463731360e21b815260040160405180910390fd5b60a0810151608081015160409091015110611634576040516301b08de360e01b815260040160405180910390fd5b6101f48160a001516101200151111561166057604051636703cded60e01b815260040160405180910390fd5b6113888160a0015161010001511180611680575060a08101516101000151155b1561169e576040516330223ae760e11b815260040160405180910390fd5b60a081015160e08101515160c09091015151146116ce57604051630204277360e11b815260040160405180910390fd5b60015460208201516040516363cd755760e11b81526001600160a01b039182166004820152600092919091169063c79aeaae90602401602060405180830381865afa158015611721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117459190612d85565b8251604051630fa6707960e21b81526001600160a01b03918216600482015291925060009190831690633e99c1e490602401600060405180830381865afa158015611794573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117bc9190810190612dbb565b905080518360a00151600001511015806117df575080518360a001516020015110155b806117f3575060a083015160208101519051145b156118115760405163a09eec5960e01b815260040160405180910390fd5b60a083015160c00151511561184a578260a0015160c001515181511461184a57604051630204277360e11b815260040160405180910390fd5b505050565b82805482825590600052602060002090810192821561188a579160200282015b8281111561188a57825182559160200191906001019061186f565b506118969291506119a3565b5090565b82805482825590600052602060002090810192821561188a579160200282015b8281111561188a57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906118ba565b6040805160e081018252600080825260208083018290528284018290528351808501909452818452830152906060820190815260200160001515815260200161199660405180610140016040528060008152602001600081526020016000815260200160006001600160a01b031681526020016000815260200160006001600160a01b03168152602001606081526020016060815260200160008152602001600081525090565b8152602001606081525090565b5b8082111561189657600081556001016119a4565b6001600160a01b038116811461157757600080fd5b6000806000604084860312156119e257600080fd5b83356119ed816119b8565b925060208401356001600160401b0380821115611a0957600080fd5b818601915086601f830112611a1d57600080fd5b813581811115611a2c57600080fd5b876020606083028501011115611a4157600080fd5b6020830194508093505050509250925092565b600060408284031215611a6657600080fd5b50919050565b60006101008284031215611a6657600080fd5b60008060608385031215611a9257600080fd5b611a9c8484611a54565b915060408301356001600160401b03811115611ab757600080fd5b611ac385828601611a6c565b9150509250929050565b600060608284031215611a6657600080fd5b600060608284031215611af157600080fd5b611afb8383611acd565b9392505050565b60008060808385031215611b1557600080fd5b611b1f8484611acd565b915060608301356001600160401b03811115611ab757600080fd5b8035611b45816119b8565b919050565b600060208284031215611b5c57600080fd5b8135611afb816119b8565b600080600060608486031215611b7c57600080fd5b83356001600160401b0380821115611b9357600080fd5b818601915086601f830112611ba757600080fd5b813581811115611bb657600080fd5b8760208260061b8501011115611bcb57600080fd5b602092830195509350611be2918791508601611a54565b90509250925092565b634e487b7160e01b600052602160045260246000fd5b60038110611c1f57634e487b7160e01b600052602160045260246000fd5b9052565b600081518084526020808501945080840160005b83811015611c5357815187529582019590820190600101611c37565b509495945050505050565b600081518084526020808501945080840160005b83811015611c535781516001600160a01b031687529582019590820190600101611c72565b60006101408251845260208301516020850152604083015160408501526060830151611cce60608601826001600160a01b03169052565b506080830151608085015260a0830151611cf360a08601826001600160a01b03169052565b5060c08301518160c0860152611d0b82860182611c23565b91505060e083015184820360e0860152611d258282611c5e565b6101008581015190870152610120948501519490950193909352509192915050565b6000815180845260005b81811015611d6d57602081850181015186830182015201611d51565b506000602082860101526020601f19601f83011685010191505092915050565b600061010060018060a01b038084511685528060208501511660208601526040840151151560408601526060840151611dca606087018251611c01565b602001511660808581019190915283015180151560a08601525060a08301518160c0860152611dfb82860182611c97565b91505060c083015184820360e0860152611e158282611d47565b95945050505050565b602081526000611afb6020830184611d8d565b634e487b7160e01b600052603260045260246000fd5b8035611e52816119b8565b6001600160a01b039081168352602082013590611e6e826119b8565b166020830152604090810135910152565b606081016114f38284611e47565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715611ec557611ec5611e8d565b60405290565b604080519081016001600160401b0381118282101715611ec557611ec5611e8d565b60405161014081016001600160401b0381118282101715611ec557611ec5611e8d565b60405160e081016001600160401b0381118282101715611ec557611ec5611e8d565b604051601f8201601f191681016001600160401b0381118282101715611f5a57611f5a611e8d565b604052919050565b8051611b45816119b8565b801515811461157757600080fd5b8051611b4581611f6d565b6003811061157757600080fd5b6000610100808385031215611fa757600080fd5b604051908101906001600160401b0382118183101715611fc957611fc9611e8d565b816040528092508351815260208401516020820152604084015160408201526060840151606082015260808401519150612002826119b8565b81608082015261201460a08501611f62565b60a082015260c084015160c082015260e084015160e0820152505092915050565b60008183036101c081121561204957600080fd5b612051611ea3565b835161205c816119b8565b8152602084015161206c816119b8565b6020820152604084015161207f81611f6d565b806040830152506040605f198301121561209857600080fd5b6120a0611ecb565b915060608401516120b081611f86565b825260808401516120c0816119b8565b6020830152606081018290526120d860a08501611f7b565b60808201526120ea8560c08601611f93565b60a0820152949350505050565b600181811c9082168061210b57607f821691505b602082108103611a6657634e487b7160e01b600052602260045260246000fd5b5b818110156113e4576000815560010161212c565b601f82111561184a57806000526020600020601f840160051c810160208510156121675750805b61074c601f850160051c83018261212b565b81516001600160401b0381111561219257612192611e8d565b6121a6816121a084546120f7565b84612140565b602080601f8311600181146121db57600084156121c35750858301515b600019600386901b1c1916600185901b178555612234565b600085815260208120601f198616915b8281101561220a578886015182559484019460019091019084016121eb565b50858210156122285787850151600019600388901b60f8161c191681555b505060018460011b0185555b505050505050565b6122468184611e47565b60806060820152600061225c6080830184611d8d565b949350505050565b60006001820161228457634e487b7160e01b600052601160045260246000fd5b5060010190565b8035611b4581611f6d565b6000604082840312156122a857600080fd5b6122b0611ecb565b905081356122bd81611f86565b815260208201356122cd816119b8565b602082015292915050565b60006001600160401b038211156122f1576122f1611e8d565b5060051b60200190565b600082601f83011261230c57600080fd5b8135602061232161231c836122d8565b611f32565b82815260059290921b8401810191818101908684111561234057600080fd5b8286015b8481101561235b5780358352918301918301612344565b509695505050505050565b600082601f83011261237757600080fd5b8135602061238761231c836122d8565b82815260059290921b840181019181810190868411156123a657600080fd5b8286015b8481101561235b5780356123bd816119b8565b83529183019183016123aa565b600061014082840312156123dd57600080fd5b6123e5611eed565b905081358152602082013560208201526040820135604082015261240b60608301611b3a565b60608201526080820135608082015261242660a08301611b3a565b60a082015260c08201356001600160401b038082111561244557600080fd5b612451858386016122fb565b60c084015260e084013591508082111561246a57600080fd5b5061247784828501612366565b60e08301525061010080830135818301525061012080830135818301525092915050565b600082601f8301126124ac57600080fd5b81356001600160401b038111156124c5576124c5611e8d565b6124d8601f8201601f1916602001611f32565b8181528460208386010111156124ed57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610100823603121561251d57600080fd5b612525611f10565b61252e83611b3a565b815261253c60208401611b3a565b602082015261254d6040840161228b565b604082015261255f3660608501612296565b606082015261257060a0840161228b565b608082015260c08301356001600160401b038082111561258f57600080fd5b61259b368387016123ca565b60a084015260e08501359150808211156125b457600080fd5b506125c13682860161249b565b60c08301525092915050565b80516001600160a01b03908116835260208083015190911690830152604090810151910152565b606081016114f382846125cd565b600081356114f3816119b8565b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081356114f381611f6d565b813561264781611f86565b6003811061266557634e487b7160e01b600052602160045260246000fd5b815460ff821691508160ff1982161783556020840135612684816119b8565b6001600160a81b03199190911690911760089190911b610100600160a81b031617905550565b6000823561013e198336030181126126c157600080fd5b9190910192915050565b6000808335601e198436030181126126e257600080fd5b8301803591506001600160401b038211156126fc57600080fd5b6020019150600581901b360382131561271457600080fd5b9250929050565b8183101561184a5780600052602060002061273a83820185830161212b565b50505050565b6001600160401b0383111561275757612757611e8d565b600160401b83111561276b5761276b611e8d565b805483825561277b84828461271b565b50818160005260208060002060005b868110156110ee578335828201559282019260010161278a565b6001600160401b038311156127bb576127bb611e8d565b600160401b8311156127cf576127cf611e8d565b80548382556127df84828461271b565b50818160005260208060002060005b868110156110ee578335612801816119b8565b82820155928201926001016127ee565b81358155602082013560018201556040820135600282015561284161283860608401612602565b6003830161260f565b6080820135600482015561286361285a60a08401612602565b6005830161260f565b61287060c08301836126cb565b61287e818360068601612740565b505061288d60e08301836126cb565b61289b8183600786016127a4565b5050610100820135600882015561012082013560098201555050565b6000808335601e198436030181126128ce57600080fd5b8301803591506001600160401b038211156128e857600080fd5b60200191503681900382131561271457600080fd5b6001600160401b0383111561291457612914611e8d565b6129288361292283546120f7565b83612140565b6000601f84116001811461295c57600085156129445750838201355b600019600387901b1c1916600186901b17835561074c565b600083815260209020601f19861690835b8281101561298d578685013582556020948501946001909201910161296d565b50868210156129aa5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81356129c7816119b8565b6129d1818361260f565b506001810160208301356129e4816119b8565b6129ee818361260f565b5060408301356129fd81611f6d565b815460ff60a01b191690151560a01b60ff60a01b16179055612a25606083016002830161263c565b612a4d612a3460a0840161262f565b6003830160ff1981541660ff8315151681178255505050565b612a66612a5d60c08401846126aa565b60048301612811565b612a7360e08301836128b7565b61273a8183600e86016128fd565b6000823561013e19833603018112612a9857600080fd5b90910192915050565b6000808335601e19843603018112612ab857600080fd5b83016020810192503590506001600160401b03811115612ad757600080fd5b8060051b360382131561271457600080fd5b81835260006001600160fb1b03831115612b0257600080fd5b8260051b80836020870137939093016020019392505050565b8183526000602080850194508260005b85811015611c53578135612b3e816119b8565b6001600160a01b031687529582019590820190600101612b2b565b6000610140823584526020830135602085015260408301356040850152612b8260608401611b3a565b6001600160a01b0316606085015260808381013590850152612ba660a08401611b3a565b6001600160a01b031660a0850152612bc160c0840184612aa1565b8260c0870152612bd48387018284612ae9565b92505050612be560e0840184612aa1565b85830360e0870152612bf8838284612b1b565b610100868101359088015261012095860135959096019490945250929392505050565b6000808335601e19843603018112612c3257600080fd5b83016020810192503590506001600160401b03811115612c5157600080fd5b80360382131561271457600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006101008235612c99816119b8565b6001600160a01b039081168552602084013590612cb5826119b8565b9081166020860152604084013590612ccc82611f6d565b9015156040860152606084013590612ce382611f86565b612cf06060870183611c01565b60808501359150612d00826119b8565b166080850152612d1260a0840161228b565b151560a0850152612d2660c0840184612a81565b8160c0860152612d3882860182612b59565b915050612d4860e0840184612c1b565b85830360e0870152612d5b838284612c60565b9695505050505050565b612d6f81846125cd565b60806060820152600061225c6080830184612c89565b600060208284031215612d9757600080fd5b8151611afb816119b8565b600060208284031215612db457600080fd5b5051919050565b60006020808385031215612dce57600080fd5b82516001600160401b03811115612de457600080fd5b8301601f81018513612df557600080fd5b8051612e0361231c826122d8565b81815260059190911b82018301908381019087831115612e2257600080fd5b928401925b82841015612e4057835182529284019290840190612e27565b979650505050505050565b612d6f8184611e47565b600060408284031215612e6757600080fd5b611afb8383612296565b8054612e808360ff8316611c01565b60081c6001600160a01b03166020929092019190915250565b6000815480845260208085019450836000528060002060005b83811015611c5357815487529582019560019182019101612eb2565b6000815480845260208085019450836000528060002060005b83811015611c535781546001600160a01b031687529582019560019182019101612ee7565b6000610140825484526001830154602085015260028301546040850152612f3d60038401546001600160a01b031690565b6001600160a01b0390811660608601526004840154608086015260058401541660a085015260c08401819052612f7881850160068501612e99565b905083810360e0850152612f8f8160078501612ece565b60088401546101008601526009909301546101209094019390935250919050565b60008154612fbd816120f7565b808552602060018381168015612fda5760018114612ff457613022565b60ff1985168884015283151560051b880183019550613022565b866000528260002060005b8581101561301a5781548a8201860152908301908401612fff565b890184019650505b505050505092915050565b61303781846125cd565b608060608201526130636080820161305684546001600160a01b031690565b6001600160a01b03169052565b60018201546001600160a01b03811660a083015260009061308e60c0840160ff8360a01c1615159052565b5061309f60e0830160028501612e71565b600383015460ff1615156101208301526101006101408301526130c9610180830160048501612f0c565b828103607f1901610160840152611e1581600e8601612fb056fe4a8c7af417003b998fff03e8f8f9b00b591215b23e38ee13eeff768daf60b0e6a26469706673582212205e30b8bb6de282046cc0a134da2ffb898d39a3bbfbdd3abb2fd28cbc836d0d3064736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000233d9067677dcf1a161954d45b4c965b9d567168000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c990000000000000000000000007f4b6f10c34470ebddf5e7ab049d8dffb01f8a6f
-----Decoded View---------------
Arg [0] : _factory (address): 0x233D9067677dCf1a161954D45B4C965B9d567168
Arg [1] : connectorRegistry (address): 0xc6013E57a0811C7111A8fB07ACd2E248D9489C99
Arg [2] : timelockAdmin (address): 0x7f4b6f10C34470ebDdF5E7ab049d8DFFb01F8A6f
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000233d9067677dcf1a161954d45b4c965b9d567168
Arg [1] : 000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c99
Arg [2] : 0000000000000000000000007f4b6f10c34470ebddf5e7ab049d8dffb01f8a6f
Loading...
Loading
Loading...
Loading

Loading...
Loading
Loading...
Loading
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.