Contract
0x60d577d0fAEA3977cB1b074f4Bb1804B5865af2C
5
Contract Overview
Balance:
0 CELO
CELO Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xf1445b94eae48f3a21d8da465fb2d6362c6747a4169e87aa39ba7571626da9d7 | 0x60806040 | 16594057 | 299 days 33 mins ago | 0x54812dbab593674cd4f1216264895be48b55c5e3 | IN | Create: CaskDCAManager | 0 CELO | 0.001953874 |
[ Download CSV Export ]
Contract Name:
CaskDCAManager
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "../interfaces/IGMXRouter.sol"; import "../job_queue/CaskJobQueue.sol"; import "../interfaces/ICaskDCAManager.sol"; import "../interfaces/ICaskDCA.sol"; import "../interfaces/ICaskVault.sol"; contract CaskDCAManager is Initializable, ReentrancyGuardUpgradeable, CaskJobQueue, ICaskDCAManager { using SafeERC20 for IERC20Metadata; uint8 private constant QUEUE_ID_DCA = 1; /** @dev Pointer to CaskDCA contract */ ICaskDCA public caskDCA; /** @dev vault to use for DCA funding. */ ICaskVault public caskVault; /** @dev merkle root of allowed assets definitions. */ bytes32 public reserved1; /** @dev map of assetSpecs that are deemed unsafe and any active DCA to them will be canceled */ mapping(bytes32 => bool) public blacklistedAssetspecs; /************************** PARAMETERS **************************/ /** @dev max number of failed DCA purchases before DCA is permanently canceled. */ uint256 public maxSkips; /** @dev DCA transaction fee in basis points. */ uint256 public dcaFeeBps; /** @dev Minimum DCA transaction fee. */ uint256 public dcaFeeMin; /** @dev Smallest allowable DCA amount. */ uint256 public dcaMinValue; /** @dev revert if price feed age is older than this number of seconds. set to 0 to disable check. */ uint256 public maxPriceFeedAge; /** @dev Address to receive DCA fees. */ address public feeDistributor; function initialize( address _caskDCA, address _caskVault, address _feeDistributor ) public initializer { require(_caskDCA != address(0), "!INVALID(caskDCA)"); require(_caskVault != address(0), "!INVALID(caskVault)"); require(_feeDistributor != address(0), "!INVALID(feeDistributor)"); caskDCA = ICaskDCA(_caskDCA); caskVault = ICaskVault(_caskVault); feeDistributor = _feeDistributor; maxSkips = 0; dcaFeeBps = 0; dcaFeeMin = 0; dcaMinValue = 0; maxPriceFeedAge = 0; __CaskJobQueue_init(3600); } /// @custom:oz-upgrades-unsafe-allow constructor constructor() initializer {} function registerDCA( bytes32 _dcaId ) override external nonReentrant whenNotPaused { processWorkUnit(QUEUE_ID_DCA, _dcaId); } function processWorkUnit( uint8 _queueId, bytes32 _dcaId ) override internal { ICaskDCA.DCA memory dca = caskDCA.getDCA(_dcaId); ICaskDCA.SwapInfo memory swapInfo = caskDCA.getSwapInfo(_dcaId); bytes32 assetSpecHash = keccak256(abi.encode(swapInfo.swapProtocol, swapInfo.swapData, dca.router, dca.priceFeed, dca.path)); if (blacklistedAssetspecs[assetSpecHash]) { caskDCA.managerCommand(_dcaId, ICaskDCA.ManagerCommand.Cancel); return; } if (dca.status != ICaskDCA.DCAStatus.Active){ return; } if (dca.amount < dcaMinValue) { caskDCA.managerCommand(_dcaId, ICaskDCA.ManagerCommand.Cancel); return; } uint32 timestamp = uint32(block.timestamp); // not time to process yet, re-queue for processAt time if (dca.processAt > timestamp) { scheduleWorkUnit(_queueId, _dcaId, bucketAt(dca.processAt)); return; } uint256 amount = dca.amount; if (dca.totalAmount > 0 && amount > dca.totalAmount - dca.currentAmount) { amount = dca.totalAmount - dca.currentAmount; } uint256 protocolFee = (amount * dcaFeeBps) / 10000; if (protocolFee < dcaFeeMin) { protocolFee = dcaFeeMin; } address inputAsset = dca.path[0]; address outputAsset = dca.path[dca.path.length-1]; ICaskVault.Asset memory inputAssetInfo = caskVault.getAsset(inputAsset); if (!inputAssetInfo.allowed) { scheduleWorkUnit(_queueId, _dcaId, bucketAt(dca.processAt + dca.period)); caskDCA.managerSkipped(_dcaId, ICaskDCA.SkipReason.AssetNotAllowed); return; } if (!_checkMinMaxPrice(dca, swapInfo, inputAssetInfo, outputAsset)) { scheduleWorkUnit(_queueId, _dcaId, bucketAt(dca.processAt + dca.period)); try caskVault.protocolPayment(dca.user, address(this), dcaFeeMin) { caskDCA.managerSkipped(_dcaId, ICaskDCA.SkipReason.OutsideLimits); if (maxSkips > 0 && dca.numSkips >= maxSkips) { caskDCA.managerCommand(_dcaId, ICaskDCA.ManagerCommand.Pause); } } catch (bytes memory) { caskDCA.managerCommand(_dcaId, ICaskDCA.ManagerCommand.Cancel); } return; } uint256 buyQty = _processDCABuy(_dcaId, dca, swapInfo, amount, protocolFee); // did a swap happen successfully? if (buyQty > 0) { if (dca.totalAmount == 0 || dca.currentAmount + amount < dca.totalAmount) { scheduleWorkUnit(_queueId, _dcaId, bucketAt(dca.processAt + dca.period)); } caskDCA.managerProcessed(_dcaId, amount, buyQty, protocolFee); } else { if (maxSkips > 0 && dca.numSkips >= maxSkips) { caskDCA.managerCommand(_dcaId, ICaskDCA.ManagerCommand.Pause); } else { scheduleWorkUnit(_queueId, _dcaId, bucketAt(dca.processAt + dca.period)); } } } function _processDCABuy( bytes32 _dcaId, ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, uint256 _amount, uint256 _protocolFee ) internal returns(uint256) { address inputAsset = dca.path[0]; uint256 beforeBalance = IERC20Metadata(inputAsset).balanceOf(address(this)); // perform a 'payment' to this contract, fee goes to vault try caskVault.protocolPayment(dca.user, address(this), _amount, 0) { // noop } catch (bytes memory) { caskDCA.managerSkipped(_dcaId, ICaskDCA.SkipReason.PaymentFailed); return 0; } // then withdraw the MASH received above as input asset to fund swap uint256 withdrawShares = caskVault.sharesForValue(_amount - _protocolFee); if (withdrawShares > caskVault.balanceOf(address(this))) { withdrawShares = caskVault.balanceOf(address(this)); } caskVault.withdraw(inputAsset, withdrawShares); // calculate actual amount of inputAsset that was received from payment/withdraw uint256 inputAmount = IERC20Metadata(inputAsset).balanceOf(address(this)) - beforeBalance; require(inputAmount > 0, "!INVALID(inputAmount)"); uint256 minOutput = _swapMinOutput(dca, swapInfo, inputAmount); if (minOutput > 0) { // ok to attempt swap uint256 amountOut = _performSwap(dca, swapInfo, inputAmount, minOutput); if (amountOut > 0) { // swap successful // any non-withdrawn vault shares are the fee portion - send to fee distributor caskVault.transfer(feeDistributor, caskVault.balanceOf(address(this))); } else { // swap failure // undo withdraw and send shares back to user IERC20Metadata(inputAsset).safeIncreaseAllowance(address(caskVault), inputAmount); caskVault.deposit(inputAsset, inputAmount); caskVault.transfer(dca.user, caskVault.balanceOf(address(this))); // refund full amount caskDCA.managerSkipped(_dcaId, ICaskDCA.SkipReason.SwapFailed); } return amountOut; } else { // excessive slippage // undo withdraw and send shares back to user IERC20Metadata(inputAsset).safeIncreaseAllowance(address(caskVault), inputAmount); caskVault.deposit(inputAsset, inputAmount); caskVault.transfer(dca.user, caskVault.balanceOf(address(this))); // refund full amount caskDCA.managerSkipped(_dcaId, ICaskDCA.SkipReason.ExcessiveSlippage); return 0; } } function _swapMinOutput( ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, uint256 _inputAmount ) internal view returns(uint256) { ICaskVault.Asset memory inputAssetInfo = caskVault.getAsset(dca.path[0]); uint256 minOutput = 0; if (dca.priceFeed != address(0)) { minOutput = _convertPrice(inputAssetInfo, dca.path[dca.path.length-1], dca.priceFeed, _inputAmount); } uint256 amountOut = _amountOut(dca, swapInfo, _inputAmount); if (minOutput > 0) { minOutput = minOutput - ((minOutput * dca.maxSlippageBps) / 10000); if (amountOut < minOutput) { return 0; // signal excessive slippage } } else { // no price feed so no excessive slippage pre-check minOutput = amountOut - ((amountOut * dca.maxSlippageBps) / 10000); } return minOutput; } function _performSwap( ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, uint256 _inputAmount, uint256 _minOutput ) internal returns(uint256) { if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.UNIV2) { return _performSwapUniV2(dca, _inputAmount, _minOutput); } else if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.UNIV3) { return _performSwapUniV3(dca, swapInfo, _inputAmount, _minOutput); } else if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.GMX) { return _performSwapGMX(dca, _inputAmount, _minOutput); } revert("!INVALID(swapProtocol)"); } function _amountOut( ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, uint256 _inputAmount ) internal view returns(uint256) { if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.UNIV2) { return _amountOutUniV2(dca, _inputAmount); } else if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.UNIV3) { require(dca.priceFeed != address(0), "!INVALID(priceFeed)"); // univ3 requires external oracle return type(uint256).max; // no direct pool slippage check for uni-v3 } else if (swapInfo.swapProtocol == ICaskDCA.SwapProtocol.GMX) { require(dca.priceFeed != address(0), "!INVALID(priceFeed)"); // gmx requires external oracle return type(uint256).max; // slippage-less trading on gmx! } revert("!INVALID(swapProtocol)"); } function _performSwapUniV2( ICaskDCA.DCA memory dca, uint256 _inputAmount, uint256 _minOutput ) internal returns(uint256) { // let swap router spend the amount of newly acquired inputAsset IERC20Metadata(dca.path[0]).safeIncreaseAllowance(dca.router, _inputAmount); uint256 buyAmount = 0; // perform swap try IUniswapV2Router02(dca.router).swapExactTokensForTokens( _inputAmount, _minOutput, dca.path, dca.to, block.timestamp + 1 hours ) returns (uint256[] memory amounts) { buyAmount = amounts[amounts.length-1]; // last amount is final output amount } catch (bytes memory) { } // buyAmount stays 0 return buyAmount; } function _amountOutUniV2( ICaskDCA.DCA memory dca, uint256 _inputAmount ) internal view returns(uint256) { uint256[] memory amountOuts = IUniswapV2Router02(dca.router).getAmountsOut(_inputAmount, dca.path); return amountOuts[amountOuts.length-1]; } function _performSwapUniV3( ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, uint256 _inputAmount, uint256 _minOutput ) internal returns(uint256) { // let swap router spend the amount of newly acquired inputAsset IERC20Metadata(dca.path[0]).safeIncreaseAllowance(dca.router, _inputAmount); uint256 buyAmount = 0; ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({ path: swapInfo.swapData, recipient: dca.to, deadline: block.timestamp + 60, amountIn: _inputAmount, amountOutMinimum: _minOutput }); // perform swap try ISwapRouter(dca.router).exactInput(params) returns (uint256 amountOut) { buyAmount = amountOut; } catch (bytes memory) { } // buyAmount stays 0 return buyAmount; } function _performSwapGMX( ICaskDCA.DCA memory dca, uint256 _inputAmount, uint256 _minOutput ) internal returns(uint256) { // let swap router spend the amount of newly acquired inputAsset IERC20Metadata(dca.path[0]).safeIncreaseAllowance(dca.router, _inputAmount); address outputAsset = dca.path[dca.path.length-1]; uint256 beforeBalance = IERC20Metadata(outputAsset).balanceOf(address(this)); // perform swap try IGMXRouter(dca.router).swap(dca.path, _inputAmount, _minOutput, dca.to) { } catch (bytes memory) {} return IERC20Metadata(outputAsset).balanceOf(address(this)) - beforeBalance; } function _checkMinMaxPrice( ICaskDCA.DCA memory dca, ICaskDCA.SwapInfo memory swapInfo, ICaskVault.Asset memory inputAssetInfo, address _outputAsset ) internal view returns(bool) { if (dca.minPrice == 0 && dca.maxPrice == 0) { return true; } uint256 pricePerOutputUnit; uint8 outputAssetDecimals = IERC20Metadata(_outputAsset).decimals(); uint256 outputAssetOneUnit = uint256(10 ** outputAssetDecimals); if (dca.priceFeed != address(0)) { // use price feed for 1 input asset unit pricePerOutputUnit = outputAssetOneUnit * outputAssetOneUnit / _convertPrice(inputAssetInfo, _outputAsset, dca.priceFeed, uint256(10 ** inputAssetInfo.assetDecimals)); } else { // use swap router price for 1 input asset unit pricePerOutputUnit = outputAssetOneUnit * outputAssetOneUnit / _amountOut(dca, swapInfo, uint256(10 ** inputAssetInfo.assetDecimals)); } if (dca.minPrice > 0 && pricePerOutputUnit < dca.minPrice) { return false; } else if (dca.maxPrice > 0 && pricePerOutputUnit > dca.maxPrice) { return false; } else { return true; } } function _convertPrice( ICaskVault.Asset memory _fromAsset, address _toAsset, address _toPriceFeed, uint256 _amount ) internal view returns(uint256) { if (_amount == 0) { return 0; } int256 oraclePrice; uint256 updatedAt; uint8 toAssetDecimals = IERC20Metadata(_toAsset).decimals(); uint8 toFeedDecimals = AggregatorV3Interface(_toPriceFeed).decimals(); ( , oraclePrice, , updatedAt, ) = AggregatorV3Interface(_fromAsset.priceFeed).latestRoundData(); uint256 fromOraclePrice = uint256(oraclePrice); require(maxPriceFeedAge == 0 || block.timestamp - updatedAt <= maxPriceFeedAge, "!PRICE_OUTDATED"); ( , oraclePrice, , updatedAt, ) = AggregatorV3Interface(_toPriceFeed).latestRoundData(); uint256 toOraclePrice = uint256(oraclePrice); require(maxPriceFeedAge == 0 || block.timestamp - updatedAt <= maxPriceFeedAge, "!PRICE_OUTDATED"); if (_fromAsset.priceFeedDecimals != toFeedDecimals) { // since oracle precision is different, scale everything // to _toAsset precision and do conversion return _scalePrice(_amount, _fromAsset.assetDecimals, toAssetDecimals) * _scalePrice(fromOraclePrice, _fromAsset.priceFeedDecimals, toAssetDecimals) / _scalePrice(toOraclePrice, toFeedDecimals, toAssetDecimals); } else { // oracles are already in same precision, so just scale _amount to oracle precision, // do the price conversion and convert back to _toAsset precision return _scalePrice( _scalePrice(_amount, _fromAsset.assetDecimals, toFeedDecimals) * fromOraclePrice / toOraclePrice, toFeedDecimals, toAssetDecimals ); } } function _scalePrice( uint256 _price, uint8 _priceDecimals, uint8 _decimals ) internal pure returns (uint256){ if (_priceDecimals < _decimals) { return _price * uint256(10 ** uint256(_decimals - _priceDecimals)); } else if (_priceDecimals > _decimals) { return _price / uint256(10 ** uint256(_priceDecimals - _decimals)); } return _price; } function setParameters( uint256 _maxSkips, uint256 _dcaFeeBps, uint256 _dcaFeeMin, uint256 _dcaMinValue, uint256 _maxPriceFeedAge, uint32 _queueBucketSize, uint32 _maxQueueAge ) external onlyOwner { require(_dcaFeeBps < 10000, "!INVALID(dcaFeeBps)"); maxSkips = _maxSkips; dcaFeeBps = _dcaFeeBps; dcaFeeMin = _dcaFeeMin; dcaMinValue = _dcaMinValue; maxPriceFeedAge = _maxPriceFeedAge; queueBucketSize = _queueBucketSize; maxQueueAge = _maxQueueAge; emit SetParameters(); } function setFeeDistributor( address _feeDistributor ) external onlyOwner { require(_feeDistributor != address(0), "!INVALID(feeDistributor)"); feeDistributor = _feeDistributor; emit SetFeeDistributor(_feeDistributor); } function blacklistAssetspec( bytes32 _assetSpec ) external onlyOwner { blacklistedAssetspecs[_assetSpec] = true; emit BlacklistAssetSpec(_assetSpec); } function unblacklistAssetspec( bytes32 _assetSpec ) external onlyOwner { blacklistedAssetspecs[_assetSpec] = false; emit UnblacklistAssetSpec(_assetSpec); } function recoverFunds( address _asset, address _dest ) external onlyOwner { IERC20Metadata(_asset).transfer(_dest, IERC20Metadata(_asset).balanceOf(address(this))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.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 a proxied contract can't have 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. * * 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 initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IGMXRouter { function swap(address[] memory _path, uint256 _amountIn, uint256 _minOut, address _receiver) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interfaces/ICaskJobQueue.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@chainlink/contracts/src/v0.8/interfaces/KeeperCompatibleInterface.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; abstract contract CaskJobQueue is Initializable, OwnableUpgradeable, PausableUpgradeable, KeeperCompatibleInterface, ReentrancyGuardUpgradeable, ICaskJobQueue { /** @dev size (in seconds) of buckets to group jobs into for processing */ uint32 public queueBucketSize; /** @dev max age (in seconds) of a bucket before a processing is triggered */ uint32 public maxQueueAge; /** @dev map used to track jobs in the queues */ mapping(uint8 => mapping(uint32 => bytes32[])) private queue; // renewal bucket => workUnit[] mapping(uint8 => uint32) private queueBucket; // current bucket being processed function __CaskJobQueue_init( uint32 _queueBucketSize ) internal onlyInitializing { __Ownable_init(); __Pausable_init(); __ICaskJobQueue_init_unchained(); __CaskJobQueue_init_unchained(_queueBucketSize); } function __CaskJobQueue_init_unchained( uint32 _queueBucketSize ) internal onlyInitializing { queueBucketSize = _queueBucketSize; maxQueueAge = queueBucketSize * 20; } function bucketAt( uint32 _timestamp ) internal view returns(uint32) { return _timestamp - (_timestamp % queueBucketSize) + queueBucketSize; } function currentBucket() internal view returns(uint32) { uint32 timestamp = uint32(block.timestamp); return timestamp - (timestamp % queueBucketSize); } function queueItem( uint8 _queueId, uint32 _bucket, uint256 _idx ) external override view returns(bytes32) { return queue[_queueId][_bucket][_idx]; } function queueSize( uint8 _queueId, uint32 _bucket ) external override view returns(uint256) { return queue[_queueId][_bucket].length; } function queuePosition( uint8 _queueId ) external override view returns(uint32) { return queueBucket[_queueId]; } function setQueuePosition( uint8 _queueId, uint32 _timestamp ) external override onlyOwner { queueBucket[_queueId] = bucketAt(_timestamp); } function checkUpkeep( bytes calldata checkData ) external view override returns(bool upkeepNeeded, bytes memory performData) { ( uint256 limit, uint256 minDepth, uint8 queueId ) = abi.decode(checkData, (uint256, uint256, uint8)); uint32 bucket = currentBucket(); upkeepNeeded = false; uint32 checkBucket = queueBucket[queueId]; if (checkBucket == 0) { checkBucket = bucket; } // if queue is over maxQueueAge and needs upkeep regardless of anything queued if (bucket >= checkBucket && bucket - checkBucket >= maxQueueAge) { upkeepNeeded = true; } else { while (checkBucket <= bucket) { if (queue[queueId][checkBucket].length > 0 && queue[queueId][checkBucket].length >= minDepth) { upkeepNeeded = true; break; } checkBucket += queueBucketSize; } } performData = abi.encode(limit, queue[queueId][checkBucket].length, queueId); } function performUpkeep( bytes calldata performData ) external override whenNotPaused nonReentrant { ( uint256 limit, uint256 depth, uint8 queueId ) = abi.decode(performData, (uint256, uint256, uint8)); uint32 bucket = currentBucket(); uint256 jobsProcessed = 0; uint256 maxBucketChecks = limit * 5; if (queueBucket[queueId] == 0) { queueBucket[queueId] = bucket; } require(queueBucket[queueId] <= bucket, "!TOO_EARLY"); while (jobsProcessed < limit && maxBucketChecks > 0 && queueBucket[queueId] <= bucket) { uint256 queueLen = queue[queueId][queueBucket[queueId]].length; if (queueLen > 0) { bytes32 workUnit = queue[queueId][queueBucket[queueId]][queueLen-1]; queue[queueId][queueBucket[queueId]].pop(); processWorkUnit(queueId, workUnit); emit WorkUnitProcessed(queueId, workUnit); jobsProcessed += 1; } else { if (queueBucket[queueId] < bucket) { queueBucket[queueId] += queueBucketSize; maxBucketChecks -= 1; } else { break; // nothing left to do } } } emit QueueRunReport(limit, jobsProcessed, depth, queueId, queue[queueId][queueBucket[queueId]].length, queueBucket[queueId]); } function requeueWorkUnit( uint8 _queueId, bytes32 _workUnit ) internal override { uint32 bucket = currentBucket(); queue[_queueId][bucket].push(_workUnit); emit WorkUnitQueued(_queueId, _workUnit, bucket); } function scheduleWorkUnit( uint8 _queueId, bytes32 _workUnit, uint32 _processAt ) internal override { // make sure we don't queue something in the past that will never get processed uint32 bucket = bucketAt(_processAt); if (bucket < queueBucket[_queueId]) { bucket = queueBucket[_queueId]; } queue[_queueId][bucket].push(_workUnit); emit WorkUnitQueued(_queueId, _workUnit, bucket); } function setQueueBucketSize( uint32 _queueBucketSize ) external override onlyOwner { queueBucketSize = _queueBucketSize; } function setMaxQueueAge( uint32 _maxQueueAge ) external override onlyOwner { maxQueueAge = _maxQueueAge; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ICaskDCAManager { function registerDCA(bytes32 _dcaId) external; /** @dev Emitted when manager parameters are changed. */ event SetParameters(); /** @dev Emitted when an assetSpec is blacklisted. */ event BlacklistAssetSpec(bytes32 indexed assetSpec); /** @dev Emitted when an assetSpec is unblacklisted. */ event UnblacklistAssetSpec(bytes32 indexed assetSpec); /** @dev Emitted the feeDistributor is changed. */ event SetFeeDistributor(address feeDistributor); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ICaskDCA { enum SwapProtocol { UNIV2, UNIV3, GMX } enum DCAStatus { None, Active, Paused, Canceled, Complete } enum ManagerCommand { None, Cancel, Skip, Pause } enum SkipReason { None, AssetNotAllowed, PaymentFailed, OutsideLimits, ExcessiveSlippage, SwapFailed } struct DCA { address user; address to; address router; address priceFeed; uint256 amount; uint256 totalAmount; uint256 currentAmount; uint256 currentQty; uint256 numBuys; uint256 numSkips; uint256 maxSlippageBps; uint256 maxPrice; uint256 minPrice; uint32 period; uint32 createdAt; uint32 processAt; DCAStatus status; address[] path; } struct SwapInfo { SwapProtocol swapProtocol; bytes swapData; } function createDCA( address[] calldata _assetSpec, // router, priceFeed, path... bytes32[] calldata _merkleProof, SwapProtocol _swapProtocol, bytes calldata _swapData, address _to, uint256[] calldata _priceSpec ) external returns(bytes32); function getDCA(bytes32 _dcaId) external view returns (DCA memory); function getSwapInfo(bytes32 _dcaId) external view returns (SwapInfo memory); function getUserDCA(address _user, uint256 _idx) external view returns (bytes32); function getUserDCACount(address _user) external view returns (uint256); function cancelDCA(bytes32 _dcaId) external; function pauseDCA(bytes32 _dcaId) external; function resumeDCA(bytes32 _dcaId) external; function managerCommand(bytes32 _dcaId, ManagerCommand _command) external; function managerProcessed(bytes32 _dcaId, uint256 _amount, uint256 _buyQty, uint256 _fee) external; function managerSkipped(bytes32 _dcaId, SkipReason _skipReason) external; event DCACreated(bytes32 indexed dcaId, address indexed user, address indexed to, address inputAsset, address outputAsset, uint256 amount, uint256 totalAmount, uint32 period); event DCAPaused(bytes32 indexed dcaId, address indexed user); event DCAResumed(bytes32 indexed dcaId, address indexed user); event DCASkipped(bytes32 indexed dcaId, address indexed user, SkipReason skipReason); event DCAProcessed(bytes32 indexed dcaId, address indexed user, uint256 amount, uint256 buyQty, uint256 fee); event DCACanceled(bytes32 indexed dcaId, address indexed user); event DCACompleted(bytes32 indexed dcaId, address indexed user); event AssetAdminChange(address indexed newAdmin); event AssetsMerkleRootChanged(bytes32 prevRoot, bytes32 newRoot); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; /** * @title Interface for vault */ interface ICaskVault is IERC20MetadataUpgradeable { // whitelisted stablecoin assets supported by the vault struct Asset { address priceFeed; uint256 slippageBps; uint256 depositLimit; uint8 assetDecimals; uint8 priceFeedDecimals; bool allowed; } enum PriceFeedType { Chainlink, Band } // sources for payments enum FundingSource { Cask, Personal } // funding profile for a given address struct FundingProfile { FundingSource fundingSource; address fundingAsset; } /** * @dev Get base asset of vault. */ function getBaseAsset() external view returns (address); /** * @dev Get all the assets supported by the vault. */ function getAllAssets() external view returns (address[] memory); /** * @dev Get asset details * @param _asset Asset address * @return Asset Asset details */ function getAsset(address _asset) external view returns(Asset memory); /** * @dev Check if the vault supports an asset * @param _asset Asset address * @return bool `true` if asset supported, `false` otherwise */ function supportsAsset(address _asset) external view returns (bool); /** * @dev Pay `_value` of `baseAsset` from `_from` to `_to` initiated by an authorized protocol * @param _from From address * @param _to To address * @param _value Amount of baseAsset value to transfer * @param _protocolFee Protocol fee to deduct from `_value` * @param _network Address of network fee collector * @param _networkFee Network fee to deduct from `_value` */ function protocolPayment( address _from, address _to, uint256 _value, uint256 _protocolFee, address _network, uint256 _networkFee ) external; /** * @dev Pay `_value` of `baseAsset` from `_from` to `_to` initiated by an authorized protocol * @param _from From address * @param _to To address * @param _value Amount of baseAsset value to transfer * @param _protocolFee Protocol fee to deduct from `_value` */ function protocolPayment( address _from, address _to, uint256 _value, uint256 _protocolFee ) external; /** * @dev Pay `_value` of `baseAsset` from `_from` to `_to` initiated by an authorized protocol * @param _from From address * @param _to To address * @param _value Amount of baseAsset value to transfer */ function protocolPayment( address _from, address _to, uint256 _value ) external; /** * @dev Transfer the equivalent vault shares of base asset `value` to `_recipient` * @param _recipient To address * @param _value Amount of baseAsset value to transfer */ function transferValue( address _recipient, uint256 _value ) external returns (bool); /** * @dev Transfer the equivalent vault shares of base asset `value` from `_sender` to `_recipient` * @param _sender From address * @param _recipient To address * @param _value Amount of baseAsset value to transfer */ function transferValueFrom( address _sender, address _recipient, uint256 _value ) external returns (bool); /** * @dev Deposit `_assetAmount` of `_asset` into the vault and credit the equivalent value of `baseAsset` * @param _asset Address of incoming asset * @param _assetAmount Amount of asset to deposit */ function deposit(address _asset, uint256 _assetAmount) external; /** * @dev Deposit `_assetAmount` of `_asset` into the vault and credit the equivalent value of `baseAsset` * @param _to Recipient of funds * @param _asset Address of incoming asset * @param _assetAmount Amount of asset to deposit */ function depositTo(address _to, address _asset, uint256 _assetAmount) external; /** * @dev Withdraw an amount of shares from the vault in the form of `_asset` * @param _asset Address of outgoing asset * @param _shares Amount of shares to withdraw */ function withdraw(address _asset, uint256 _shares) external; /** * @dev Withdraw an amount of shares from the vault in the form of `_asset` * @param _recipient Recipient who will receive the withdrawn assets * @param _asset Address of outgoing asset * @param _shares Amount of shares to withdraw */ function withdrawTo(address _recipient, address _asset, uint256 _shares) external; /** * @dev Retrieve the funding source for an address * @param _address Address for lookup */ function fundingSource(address _address) external view returns(FundingProfile memory); /** * @dev Set the funding source and, if using a personal wallet, the asset to use for funding payments * @param _fundingSource Funding source to use * @param _fundingAsset Asset to use for payments (if using personal funding source) */ function setFundingSource(FundingSource _fundingSource, address _fundingAsset) external; /** * @dev Get current vault value of `_address` denominated in `baseAsset` * @param _address Address to check */ function currentValueOf(address _address) external view returns(uint256); /** * @dev Get current vault value a vault share */ function pricePerShare() external view returns(uint256); /** * @dev Get the number of vault shares that represents a given value of the base asset * @param _value Amount of value */ function sharesForValue(uint256 _value) external view returns(uint256); /** * @dev Get total value in vault and managed by admin - denominated in `baseAsset` */ function totalValue() external view returns(uint256); /** * @dev Get total amount of an asset held in vault and managed by admin * @param _asset Address of asset */ function totalAssetBalance(address _asset) external view returns(uint256); /************************** EVENTS **************************/ /** @dev Emitted when `sender` transfers `baseAssetValue` (denominated in vault baseAsset) to `recipient` */ event TransferValue(address indexed from, address indexed to, uint256 baseAssetAmount, uint256 shares); /** @dev Emitted when an amount of `baseAsset` is paid from `from` to `to` within the vault */ event Payment(address indexed from, address indexed to, uint256 baseAssetAmount, uint256 shares, uint256 protocolFee, uint256 protocolFeeShares, address indexed network, uint256 networkFee, uint256 networkFeeShares); /** @dev Emitted when `asset` is added as a new supported asset */ event AllowedAsset(address indexed asset); /** @dev Emitted when `asset` is disallowed t */ event DisallowedAsset(address indexed asset); /** @dev Emitted when `participant` deposits `asset` */ event AssetDeposited(address indexed participant, address indexed asset, uint256 assetAmount, uint256 baseAssetAmount, uint256 shares); /** @dev Emitted when `participant` withdraws `asset` */ event AssetWithdrawn(address indexed participant, address indexed asset, uint256 assetAmount, uint256 baseAssetAmount, uint256 shares); /** @dev Emitted when `participant` sets their funding source */ event SetFundingSource(address indexed participant, FundingSource fundingSource, address fundingAsset); /** @dev Emitted when a new protocol is allowed to use the vault */ event AddProtocol(address indexed protocol); /** @dev Emitted when a protocol is no longer allowed to use the vault */ event RemoveProtocol(address indexed protocol); /** @dev Emitted when the vault price feed type is changed */ event SetPriceFeedType(PriceFeedType priceFeedType); /** @dev Emitted when the vault fee distributor is changed */ event SetFeeDistributor(address indexed feeDistributor); /** @dev Emitted when minDeposit is changed */ event SetMinDeposit(uint256 minDeposit); /** @dev Emitted when maxPriceFeedAge is changed */ event SetMaxPriceFeedAge(uint256 maxPriceFeedAge); /** @dev Emitted when the trustedForwarder address is changed */ event SetTrustedForwarder(address indexed feeDistributor); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; abstract contract ICaskJobQueue is Initializable { function __ICaskJobQueue_init() internal onlyInitializing { __ICaskJobQueue_init_unchained(); } function __ICaskJobQueue_init_unchained() internal onlyInitializing { } function processWorkUnit(uint8 _queueId, bytes32 _workUnit) virtual internal; function requeueWorkUnit(uint8 _queueId, bytes32 _workUnit) virtual internal; function scheduleWorkUnit(uint8 _queueId, bytes32 _workUnit, uint32 _processAt) virtual internal; function queueItem(uint8 _queueId, uint32 _bucket, uint256 _idx) virtual external view returns(bytes32); function queueSize(uint8 _queueId, uint32 _bucket) virtual external view returns(uint256); function queuePosition(uint8 _queueId) virtual external view returns(uint32); function setQueuePosition(uint8 _queueId, uint32 _timestamp) virtual external; function setQueueBucketSize(uint32 _queueBucketSize) virtual external; function setMaxQueueAge(uint32 _maxQueueAge) virtual external; event WorkUnitProcessed(uint8 queueId, bytes32 workUnit); event WorkUnitQueued(uint8 queueId, bytes32 workUnit, uint32 processAt); /** @dev Emitted when a queue run is finished */ event QueueRunReport(uint256 limit, uint256 jobsProcessed, uint256 depth, uint8 queueId, uint256 queueRemaining, uint32 currentBucket); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface KeeperCompatibleInterface { /** * @notice method that is simulated by the keepers to see if any work actually * needs to be performed. This method does does not actually need to be * executable, and since it is only ever simulated it can consume lots of gas. * @dev To ensure that it is never called, you may want to add the * cannotExecute modifier from KeeperBase to your implementation of this * method. * @param checkData specified in the upkeep registration so it is always the * same for a registered upkeep. This can easilly be broken down into specific * arguments using `abi.decode`, so multiple upkeeps can be registered on the * same contract and easily differentiated by the contract. * @return upkeepNeeded boolean to indicate whether the keeper should call * performUpkeep or not. * @return performData bytes that the keeper should call performUpkeep with, if * upkeep is needed. If you would like to encode data to decode later, try * `abi.encode`. */ function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); /** * @notice method that is actually executed by the keepers, via the registry. * The data returned by the checkUpkeep simulation will be passed into * this method to actually be executed. * @dev The input to this method should not be trusted, and the caller of the * method should not even be restricted to any single registry. Anyone should * be able call it, and the input should be validated, there is no guarantee * that the data passed in is the performData returned from checkUpkeep. This * could happen due to malicious keepers, racing keepers, or simply a state * change while the performUpkeep transaction is waiting for confirmation. * Always validate the data passed in. * @param performData is the data which was passed back from the checkData * simulation. If it is encoded, it can easily be decoded into other types by * calling `abi.decode`. This data should not be trusted, and should be * validated against the contract's current state. */ function performUpkeep(bytes calldata performData) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Context_init_unchained(); __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assetSpec","type":"bytes32"}],"name":"BlacklistAssetSpec","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"jobsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depth","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"queueId","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"queueRemaining","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"currentBucket","type":"uint32"}],"name":"QueueRunReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeDistributor","type":"address"}],"name":"SetFeeDistributor","type":"event"},{"anonymous":false,"inputs":[],"name":"SetParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assetSpec","type":"bytes32"}],"name":"UnblacklistAssetSpec","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"queueId","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"workUnit","type":"bytes32"}],"name":"WorkUnitProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"queueId","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"workUnit","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"processAt","type":"uint32"}],"name":"WorkUnitQueued","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_assetSpec","type":"bytes32"}],"name":"blacklistAssetspec","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"blacklistedAssetspecs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"caskDCA","outputs":[{"internalType":"contract ICaskDCA","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"caskVault","outputs":[{"internalType":"contract ICaskVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"checkData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dcaFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dcaFeeMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dcaMinValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_caskDCA","type":"address"},{"internalType":"address","name":"_caskVault","type":"address"},{"internalType":"address","name":"_feeDistributor","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxPriceFeedAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxQueueAge","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSkips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"queueBucketSize","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_queueId","type":"uint8"},{"internalType":"uint32","name":"_bucket","type":"uint32"},{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"queueItem","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_queueId","type":"uint8"}],"name":"queuePosition","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_queueId","type":"uint8"},{"internalType":"uint32","name":"_bucket","type":"uint32"}],"name":"queueSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_dest","type":"address"}],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_dcaId","type":"bytes32"}],"name":"registerDCA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserved1","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeDistributor","type":"address"}],"name":"setFeeDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_maxQueueAge","type":"uint32"}],"name":"setMaxQueueAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSkips","type":"uint256"},{"internalType":"uint256","name":"_dcaFeeBps","type":"uint256"},{"internalType":"uint256","name":"_dcaFeeMin","type":"uint256"},{"internalType":"uint256","name":"_dcaMinValue","type":"uint256"},{"internalType":"uint256","name":"_maxPriceFeedAge","type":"uint256"},{"internalType":"uint32","name":"_queueBucketSize","type":"uint32"},{"internalType":"uint32","name":"_maxQueueAge","type":"uint32"}],"name":"setParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_queueBucketSize","type":"uint32"}],"name":"setQueueBucketSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_queueId","type":"uint8"},{"internalType":"uint32","name":"_timestamp","type":"uint32"}],"name":"setQueuePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_assetSpec","type":"bytes32"}],"name":"unblacklistAssetspec","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50600054610100900460ff166200002f5760005460ff161562000039565b62000039620000de565b620000a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c4576000805461ffff19166101011790555b8015620000d7576000805461ff00191690555b5062000102565b6000620000f630620000fc60201b6200129a1760201c565b15905090565b3b151590565b61454780620001126000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063715018a61161010f578063ab4de5ed116100a2578063ccfc2e8d11610071578063ccfc2e8d14610422578063cd48a61414610435578063f2fde38b14610448578063fa184a1e1461045b57600080fd5b8063ab4de5ed146103e5578063c0c53b8b146103ee578063c506465314610401578063c6f8806c1461040a57600080fd5b806390c6da56116100de57806390c6da56146103a3578063a47755d1146103b6578063aa878f76146103c9578063aaac831f146103dc57600080fd5b8063715018a614610367578063729d81071461036f5780638bddd2e4146103825780638da5cb5b1461039257600080fd5b80631c39033c1161018757806335e53b941161015657806335e53b94146102f55780634585e33b146103285780635c975abb1461033b5780636e04ff0d1461034657600080fd5b80631c39033c146102885780631e8506d6146102c657806324ae6a27146102d957806330f01be8146102ec57600080fd5b80630caae41d116101c35780630caae41d146102465780630d43e8ad1461025957806314fad7071461026c5780631ac6c56b1461027f57600080fd5b806308058e7c146101ea5780630816c8471461021a5780630abe19d914610231575b600080fd5b60cc546101fd906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61022360d45481565b604051908152602001610211565b61024461023f36600461379e565b61046e565b005b610244610254366004613816565b61055a565b60d5546101fd906001600160a01b031681565b61022361027a36600461384f565b6105bc565b61022360d15481565b6102b1610296366004613890565b60ff16600090815260cb602052604090205463ffffffff1690565b60405163ffffffff9091168152602001610211565b6102446102d43660046138ad565b610606565b6102446102e73660046138db565b610673565b61022360d35481565b6103186103033660046138ad565b60cf6020526000908152604090205460ff1681565b6040519015158152602001610211565b610244610336366004613909565b6107a1565b60655460ff16610318565b610359610354366004613909565b610b99565b6040516102119291906139d3565b610244610d18565b61024461037d3660046139ee565b610d4e565b60c9546102b19063ffffffff1681565b6033546001600160a01b03166101fd565b6102446103b13660046138ad565b610da0565b60cd546101fd906001600160a01b031681565b6102236103d7366004613816565b610e0a565b61022360ce5481565b61022360d25481565b6102446103fc366004613a0b565b610e35565b61022360d05481565b60c9546102b190640100000000900463ffffffff1681565b610244610430366004613a56565b611039565b6102446104433660046139ee565b611108565b610244610456366004613a56565b61114e565b6102446104693660046138ad565b6111e9565b6033546001600160a01b031633146104a15760405162461bcd60e51b815260040161049890613a73565b60405180910390fd5b61271086106104e85760405162461bcd60e51b815260206004820152601360248201527221494e56414c4944286463614665654270732960681b6044820152606401610498565b60d087905560d186905560d285905560d384905560d483905560c9805463ffffffff8381166401000000000267ffffffffffffffff19909216908516171790556040517f3b5fda6f71b960b21be0b432d9b7c87d9c8c996477ea1eba5c19cb77d1e027aa90600090a150505050505050565b6033546001600160a01b031633146105845760405162461bcd60e51b815260040161049890613a73565b61058d816112a0565b60ff92909216600090815260cb60205260409020805463ffffffff191663ffffffff9093169290921790915550565b60ff8316600090815260ca6020908152604080832063ffffffff8616845290915281208054839081106105f1576105f1613aa8565b906000526020600020015490505b9392505050565b6033546001600160a01b031633146106305760405162461bcd60e51b815260040161049890613a73565b600081815260cf6020526040808220805460ff191660011790555182917f24b2f8b1797db190508a9ea995ccc6b8f33928a8ec4fb3a27504f51e1157647b91a250565b6033546001600160a01b0316331461069d5760405162461bcd60e51b815260040161049890613a73565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a082319060240160206040518083038186803b1580156106e657600080fd5b505afa1580156106fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071e9190613abe565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561076457600080fd5b505af1158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079c9190613aec565b505050565b60655460ff16156107e75760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610498565b6002609754141561083a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610498565b60026097556000808061084f84860186613b07565b925092509250600061085f6112ca565b905060008061086f866005613b4b565b60ff8516600090815260cb602052604090205490915063ffffffff166108b55760ff8416600090815260cb60205260409020805463ffffffff191663ffffffff85161790555b60ff8416600090815260cb602052604090205463ffffffff8085169116111561090d5760405162461bcd60e51b815260206004820152600a60248201526921544f4f5f4541524c5960b01b6044820152606401610498565b858210801561091c5750600081115b8015610943575060ff8416600090815260cb602052604090205463ffffffff808516911611155b15610b025760ff8416600090815260ca6020908152604080832060cb83528184205463ffffffff1684529091529020548015610a725760ff8516600090815260ca6020908152604080832060cb83528184205463ffffffff16845290915281206109ae600184613b6a565b815481106109be576109be613aa8565b600091825260208083209091015460ff8916835260ca8252604080842060cb84528185205463ffffffff168552909252912080549192509080610a0357610a03613b81565b60019003818190600052602060002001600090559055610a2386826112f2565b6040805160ff88168152602081018390527f58c7ae721fd25aaf84e68db9ce9ac6fed4f08438a370a4299d19f8c1425c499e910160405180910390a1610a6a600185613b97565b935050610afc565b60ff8516600090815260cb602052604090205463ffffffff80861691161015610af65760c95460ff8616600090815260cb60205260408120805463ffffffff93841693919291610ac491859116613baf565b92506101000a81548163ffffffff021916908363ffffffff160217905550600182610aef9190613b6a565b9150610afc565b50610b02565b5061090d565b60ff8416600081815260ca6020908152604080832060cb8084528285205463ffffffff168086529184528285205494869052835281518b81529283018790528282018a90526060830194909452608082019290925260a0810192909252517fd69140f88b9a25350749bb371882f4479133fc8b65602aac60f6c1b3598f08329181900360c00190a150506001609755505050505050565b60006060818080610bac86880188613b07565b9250925092506000610bbc6112ca565b60ff8316600090815260cb602052604081205490975090915063ffffffff1680610be35750805b8063ffffffff168263ffffffff1610158015610c1e575060c954640100000000900463ffffffff16610c158284613bd7565b63ffffffff1610155b15610c2c5760019650610cbc565b8163ffffffff168163ffffffff1611610cbc5760ff8316600090815260ca6020908152604080832063ffffffff8516845290915290205415801590610c94575060ff8316600090815260ca6020908152604080832063ffffffff851684529091529020548411155b15610ca25760019650610cbc565b60c954610cb59063ffffffff1682613baf565b9050610c2c565b60ff8316600081815260ca6020908152604080832063ffffffff86168452825291829020548251918201899052918101919091526060810191909152608001604051602081830303815290604052955050505050509250929050565b6033546001600160a01b03163314610d425760405162461bcd60e51b815260040161049890613a73565b610d4c6000611aa3565b565b6033546001600160a01b03163314610d785760405162461bcd60e51b815260040161049890613a73565b60c9805463ffffffff9092166401000000000267ffffffff0000000019909216919091179055565b6033546001600160a01b03163314610dca5760405162461bcd60e51b815260040161049890613a73565b600081815260cf6020526040808220805460ff191690555182917fba894bc0c7e4bd24c200bbd3877abd49470e2d8d96aeaecae8a02e09809e4aea91a250565b60ff8216600090815260ca6020908152604080832063ffffffff851684529091529020545b92915050565b600054610100900460ff16610e505760005460ff1615610e54565b303b155b610eb75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610498565b600054610100900460ff16158015610ed9576000805461ffff19166101011790555b6001600160a01b038416610f235760405162461bcd60e51b815260206004820152601160248201527021494e56414c4944286361736b4443412960781b6044820152606401610498565b6001600160a01b038316610f6f5760405162461bcd60e51b815260206004820152601360248201527221494e56414c4944286361736b5661756c742960681b6044820152606401610498565b6001600160a01b038216610fc05760405162461bcd60e51b815260206004820152601860248201527721494e56414c4944286665654469737472696275746f722960401b6044820152606401610498565b60cc80546001600160a01b038087166001600160a01b03199283161790925560cd805486841690831617905560d5805492851692909116919091179055600060d081905560d181905560d281905560d381905560d455611021610e10611af5565b8015611033576000805461ff00191690555b50505050565b6033546001600160a01b031633146110635760405162461bcd60e51b815260040161049890613a73565b6001600160a01b0381166110b45760405162461bcd60e51b815260206004820152601860248201527721494e56414c4944286665654469737472696275746f722960401b6044820152606401610498565b60d580546001600160a01b0319166001600160a01b0383169081179091556040519081527f9e9a9a4a82acd1b28aab6bf1d43aad70ae6d290549c0d6183e2e91ebcdf574419060200160405180910390a150565b6033546001600160a01b031633146111325760405162461bcd60e51b815260040161049890613a73565b60c9805463ffffffff191663ffffffff92909216919091179055565b6033546001600160a01b031633146111785760405162461bcd60e51b815260040161049890613a73565b6001600160a01b0381166111dd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610498565b6111e681611aa3565b50565b6002609754141561123c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610498565b600260975560655460ff16156112875760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610498565b6112926001826112f2565b506001609755565b3b151590565b60c95460009063ffffffff166112b68184613c12565b6112c09084613bd7565b610e2f9190613baf565b60c95460009042906112e29063ffffffff1682613c12565b6112ec9082613bd7565b91505090565b60cc546040516392c65f4b60e01b8152600481018390526000916001600160a01b0316906392c65f4b9060240160006040518083038186803b15801561133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113739190810190613d86565b60cc54604051630b43f1ad60e21b8152600481018590529192506000916001600160a01b0390911690632d0fc6b49060240160006040518083038186803b1580156113bd57600080fd5b505afa1580156113d1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113f99190810190613ee3565b90506000816000015182602001518460400151856060015186610220015160405160200161142b959493929190614011565b60408051601f198184030181529181528151602092830120600081815260cf90935291205490915060ff16156114c75760cc54604051635ba581cd60e01b81526001600160a01b0390911690635ba581cd9061148e90879060019060040161406f565b600060405180830381600087803b1580156114a857600080fd5b505af11580156114bc573d6000803e3d6000fd5b505050505050505050565b600183610200015160048111156114e0576114e0613fb7565b146114ec575050505050565b60d3548360800151101561152d5760cc54604051635ba581cd60e01b81526001600160a01b0390911690635ba581cd9061148e90879060019060040161406f565b6101e0830151429063ffffffff808316911611156115655761155d8686611558876101e001516112a0565b611b3d565b505050505050565b608084015160a08501511580159061158f57508460c001518560a0015161158c9190613b6a565b81115b156115ab578460c001518560a001516115a89190613b6a565b90505b600061271060d154836115be9190613b4b565b6115c89190614093565b905060d2548110156115d9575060d2545b60008661022001516000815181106115f3576115f3613aa8565b6020026020010151905060008761022001516001896102200151516116189190613b6a565b8151811061162857611628613aa8565b602090810291909101015160cd5460405163185c596360e11b81526001600160a01b038581166004830152929350600092909116906330b8b2c69060240160c06040518083038186803b15801561167e57600080fd5b505afa158015611692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b691906140a7565b90508060a00151611756576116e48b8b6115588c6101a001518d6101e001516116df9190613baf565b6112a0565b60cc54604051632a74cbb560e01b81526001600160a01b0390911690632a74cbb590611717908d90600190600401614140565b600060405180830381600087803b15801561173157600080fd5b505af1158015611745573d6000803e3d6000fd5b505050505050505050505050505050565b61176289898385611c05565b611950576117848b8b6115588c6101a001518d6101e001516116df9190613baf565b60cd54895160d254604051638e3e580d60e01b81526001600160a01b0392831660048201523060248201526044810191909152911690638e3e580d90606401600060405180830381600087803b1580156117dd57600080fd5b505af19250505080156117ee575060015b61188d573d80801561181c576040519150601f19603f3d011682016040523d82523d6000602084013e611821565b606091505b5060cc54604051635ba581cd60e01b81526001600160a01b0390911690635ba581cd90611855908e9060019060040161406f565b600060405180830381600087803b15801561186f57600080fd5b505af1158015611883573d6000803e3d6000fd5b5050505050611943565b60cc54604051632a74cbb560e01b81526001600160a01b0390911690632a74cbb5906118c0908d90600390600401614140565b600060405180830381600087803b1580156118da57600080fd5b505af11580156118ee573d6000803e3d6000fd5b50505050600060d05411801561190b575060d05489610120015110155b156119435760cc54604051635ba581cd60e01b81526001600160a01b0390911690635ba581cd90611717908d9060039060040161406f565b5050505050505050505050565b600061195f8b8b8b8989611d96565b90508015611a265760a08a0151158061198a57508960a00151868b60c001516119889190613b97565b105b156119ad576119ad8c8c6115588d6101a001518e6101e001516116df9190613baf565b60cc54604051632d32f27960e21b8152600481018d90526024810188905260448101839052606481018790526001600160a01b039091169063b4cbc9e4906084015b600060405180830381600087803b158015611a0957600080fd5b505af1158015611a1d573d6000803e3d6000fd5b50505050611a95565b600060d054118015611a3f575060d0548a610120015110155b15611a775760cc54604051635ba581cd60e01b81526001600160a01b0390911690635ba581cd906119ef908e9060039060040161406f565b611a958c8c6115588d6101a001518e6101e001516116df9190613baf565b505050505050505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611b1c5760405162461bcd60e51b815260040161049890614157565b611b2461273b565b611b2c612772565b611b346127a9565b6111e6816127d0565b6000611b48826112a0565b60ff8516600090815260cb602052604090205490915063ffffffff9081169082161015611b8a575060ff8316600090815260cb602052604090205463ffffffff165b60ff8416600081815260ca6020908152604080832063ffffffff861680855290835281842080546001810182559085529383902090930187905580519384529083018690528201527f67778e52b18dcf574ab071142a886fce91a8ce5e60e176229fdadb8c063caaed9060600160405180910390a150505050565b60008461018001516000148015611c1f5750610160850151155b15611c2c57506001611d8e565b600080836001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611c6857600080fd5b505afa158015611c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca091906141a2565b90506000611caf82600a6142a3565b60608901519091506001600160a01b031615611d0057611ce586868a606001518960600151600a611ce091906142a3565b61283d565b611cef8280613b4b565b611cf99190614093565b9250611d32565b611d1b88888860600151600a611d1691906142a3565b612b6d565b611d258280613b4b565b611d2f9190614093565b92505b6000886101800151118015611d4b575087610180015183105b15611d5c5760009350505050611d8e565b6000886101600151118015611d75575087610160015183115b15611d865760009350505050611d8e565b600193505050505b949350505050565b600080856102200151600081518110611db157611db1613aa8565b60209081029190910101516040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015611e0157600080fd5b505afa158015611e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e399190613abe565b60cd54885160405163fcd6a25b60e01b81526001600160a01b0391821660048201523060248201526044810189905260006064820152929350169063fcd6a25b90608401600060405180830381600087803b158015611e9757600080fd5b505af1925050508015611ea8575060015b611f4d573d808015611ed6576040519150601f19603f3d011682016040523d82523d6000602084013e611edb565b606091505b5060cc54604051632a74cbb560e01b81526001600160a01b0390911690632a74cbb590611f0f908c90600290600401614140565b600060405180830381600087803b158015611f2957600080fd5b505af1158015611f3d573d6000803e3d6000fd5b5050505060009350505050612732565b60cd546000906001600160a01b031663e1ded2de611f6b8789613b6a565b6040518263ffffffff1660e01b8152600401611f8991815260200190565b60206040518083038186803b158015611fa157600080fd5b505afa158015611fb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd99190613abe565b60cd546040516370a0823160e01b81523060048201529192506001600160a01b0316906370a082319060240160206040518083038186803b15801561201d57600080fd5b505afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120559190613abe565b8111156120da5760cd546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561209f57600080fd5b505afa1580156120b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d79190613abe565b90505b60cd5460405163f3fef3a360e01b81526001600160a01b038581166004830152602482018490529091169063f3fef3a390604401600060405180830381600087803b15801561212857600080fd5b505af115801561213c573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092508491506001600160a01b038616906370a082319060240160206040518083038186803b15801561218457600080fd5b505afa158015612198573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121bc9190613abe565b6121c69190613b6a565b9050600081116122105760405162461bcd60e51b815260206004820152601560248201527421494e56414c494428696e707574416d6f756e742960581b6044820152606401610498565b600061221d8a8a84612cba565b9050801561253f5760006122338b8b8585612e54565b905080156123475760cd5460d5546040516370a0823160e01b81523060048201526001600160a01b039283169263a9059cbb92169083906370a082319060240160206040518083038186803b15801561228b57600080fd5b505afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c39190613abe565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561230957600080fd5b505af115801561231d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123419190613aec565b50612532565b60cd54612361906001600160a01b03888116911685612ecf565b60cd546040516311f9fbc960e21b81526001600160a01b03888116600483015260248201869052909116906347e7ef2490604401600060405180830381600087803b1580156123af57600080fd5b505af11580156123c3573d6000803e3d6000fd5b505060cd548d516040516370a0823160e01b81523060048201526001600160a01b03909216935063a9059cbb92509083906370a082319060240160206040518083038186803b15801561241557600080fd5b505afa158015612429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244d9190613abe565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561249357600080fd5b505af11580156124a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124cb9190613aec565b5060cc54604051632a74cbb560e01b81526001600160a01b0390911690632a74cbb5906124ff908f90600590600401614140565b600060405180830381600087803b15801561251957600080fd5b505af115801561252d573d6000803e3d6000fd5b505050505b9550612732945050505050565b60cd54612559906001600160a01b03878116911684612ecf565b60cd546040516311f9fbc960e21b81526001600160a01b03878116600483015260248201859052909116906347e7ef2490604401600060405180830381600087803b1580156125a757600080fd5b505af11580156125bb573d6000803e3d6000fd5b505060cd548c516040516370a0823160e01b81523060048201526001600160a01b03909216935063a9059cbb92509083906370a082319060240160206040518083038186803b15801561260d57600080fd5b505afa158015612621573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126459190613abe565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561268b57600080fd5b505af115801561269f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c39190613aec565b5060cc54604051632a74cbb560e01b81526001600160a01b0390911690632a74cbb5906126f6908e906004908101614140565b600060405180830381600087803b15801561271057600080fd5b505af1158015612724573d6000803e3d6000fd5b505050506000955050505050505b95945050505050565b600054610100900460ff166127625760405162461bcd60e51b815260040161049890614157565b61276a6127a9565b610d4c612fb2565b600054610100900460ff166127995760405162461bcd60e51b815260040161049890614157565b6127a16127a9565b610d4c612fe2565b600054610100900460ff16610d4c5760405162461bcd60e51b815260040161049890614157565b600054610100900460ff166127f75760405162461bcd60e51b815260040161049890614157565b60c9805463ffffffff191663ffffffff831690811790915561281a9060146142b2565b60c960046101000a81548163ffffffff021916908363ffffffff16021790555050565b60008161284c57506000611d8e565b6000806000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561288a57600080fd5b505afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c291906141a2565b90506000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156128ff57600080fd5b505afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061293791906141a2565b905088600001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561297657600080fd5b505afa15801561298a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ae91906142f8565b5060d45492975095508692505015806129d2575060d4546129cf8542613b6a565b11155b612a105760405162461bcd60e51b815260206004820152600f60248201526e0854149250d157d3d5551110551151608a1b6044820152606401610498565b876001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015612a4957600080fd5b505afa158015612a5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8191906142f8565b5060d4549298509650879250501580612aa5575060d454612aa28642613b6a565b11155b612ae35760405162461bcd60e51b815260206004820152600f60248201526e0854149250d157d3d5551110551151608a1b6044820152606401610498565b8260ff168b6080015160ff1614612b3e57612aff818486613015565b612b0e838d6080015187613015565b612b1d8a8e6060015188613015565b612b279190613b4b565b612b319190614093565b9650505050505050611d8e565b612b318183612b528b8f6060015188613015565b612b5c9190613b4b565b612b669190614093565b8486613015565b60008083516002811115612b8357612b83613fb7565b1415612b9a57612b93848361307f565b90506105ff565b600183516002811115612baf57612baf613fb7565b1415612c0e5760608401516001600160a01b0316612c055760405162461bcd60e51b815260206004820152601360248201527221494e56414c4944287072696365466565642960681b6044820152606401610498565b506000196105ff565b600283516002811115612c2357612c23613fb7565b1415612c795760608401516001600160a01b0316612c055760405162461bcd60e51b815260206004820152601360248201527221494e56414c4944287072696365466565642960681b6044820152606401610498565b60405162461bcd60e51b815260206004820152601660248201527521494e56414c4944287377617050726f746f636f6c2960501b6044820152606401610498565b60cd54610220840151805160009283926001600160a01b03909116916330b8b2c691908490612ceb57612ceb613aa8565b60200260200101516040518263ffffffff1660e01b8152600401612d1e91906001600160a01b0391909116815260200190565b60c06040518083038186803b158015612d3657600080fd5b505afa158015612d4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6e91906140a7565b60608601519091506000906001600160a01b031615612dc7576102208601518051612dc4918491612da190600190613b6a565b81518110612db157612db1613aa8565b602002602001015188606001518761283d565b90505b6000612dd4878787612b6d565b90508115612e1f5761271087610140015183612df09190613b4b565b612dfa9190614093565b612e049083613b6a565b915081811015612e1a57600093505050506105ff565b612e4a565b61271087610140015182612e339190613b4b565b612e3d9190614093565b612e479082613b6a565b91505b5095945050505050565b60008084516002811115612e6a57612e6a613fb7565b1415612e8257612e7b85848461313f565b9050611d8e565b600184516002811115612e9757612e97613fb7565b1415612ea957612e7b8585858561328d565b600284516002811115612ebe57612ebe613fb7565b1415612c7957612e7b8584846133ad565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015612f1b57600080fd5b505afa158015612f2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f539190613abe565b612f5d9190613b97565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790529091506110339085906135af565b600054610100900460ff16612fd95760405162461bcd60e51b815260040161049890614157565b610d4c33611aa3565b600054610100900460ff166130095760405162461bcd60e51b815260040161049890614157565b6065805460ff19169055565b60008160ff168360ff1610156130475761302f8383614348565b61303d9060ff16600a61436b565b612b939085613b4b565b8160ff168360ff1611156130775761305f8284614348565b61306d9060ff16600a61436b565b612b939085614093565b509192915050565b60008083604001516001600160a01b031663d06ca61f848661022001516040518363ffffffff1660e01b81526004016130b9929190614377565b60006040518083038186803b1580156130d157600080fd5b505afa1580156130e5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261310d9190810190614390565b9050806001825161311e9190613b6a565b8151811061312e5761312e613aa8565b602002602001015191505092915050565b600061318284604001518486610220015160008151811061316257613162613aa8565b60200260200101516001600160a01b0316612ecf9092919063ffffffff16565b600084604001516001600160a01b03166338ed17398585886102200151896020015142610e106131b29190613b97565b6040518663ffffffff1660e01b81526004016131d2959493929190614416565b600060405180830381600087803b1580156131ec57600080fd5b505af192505050801561322157506040513d6000823e601f3d908101601f1916820160405261321e9190810190614390565b60015b61325b573d80801561324f576040519150601f19603f3d011682016040523d82523d6000602084013e613254565b606091505b5050611d8e565b806001825161326a9190613b6a565b8151811061327a5761327a613aa8565b6020026020010151915050949350505050565b60006132b085604001518487610220015160008151811061316257613162613aa8565b6000806040518060a001604052808760200151815260200188602001516001600160a01b0316815260200142603c6132e89190613b97565b815260200186815260200185815250905086604001516001600160a01b031663c04b8d59826040518263ffffffff1660e01b81526004016133299190614452565b602060405180830381600087803b15801561334357600080fd5b505af1925050508015613373575060408051601f3d908101601f1916820190925261337091810190613abe565b60015b612e47573d8080156133a1576040519150601f19603f3d011682016040523d82523d6000602084013e6133a6565b606091505b5050612e4a565b60006133d084604001518486610220015160008151811061316257613162613aa8565b6102208401518051600091906133e890600190613b6a565b815181106133f8576133f8613aa8565b60209081029190910101516040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134809190613abe565b905085604001516001600160a01b0316636023e96687610220015187878a602001516040518563ffffffff1660e01b81526004016134c194939291906144aa565b600060405180830381600087803b1580156134db57600080fd5b505af19250505080156134ec575060015b613522573d80801561351a576040519150601f19603f3d011682016040523d82523d6000602084013e61351f565b606091505b50505b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a082319060240160206040518083038186803b15801561356357600080fd5b505afa158015613577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359b9190613abe565b6135a59190613b6a565b9695505050505050565b6000613604826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136819092919063ffffffff16565b80519091501561079c57808060200190518101906136229190613aec565b61079c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610498565b6060611d8e848460008585843b6136da5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610498565b600080866001600160a01b031685876040516136f691906144e2565b60006040518083038185875af1925050503d8060008114613733576040519150601f19603f3d011682016040523d82523d6000602084013e613738565b606091505b5091509150613748828286613753565b979650505050505050565b606083156137625750816105ff565b8251156137725782518084602001fd5b8160405162461bcd60e51b815260040161049891906144fe565b63ffffffff811681146111e657600080fd5b600080600080600080600060e0888a0312156137b957600080fd5b873596506020880135955060408801359450606088013593506080880135925060a08801356137e78161378c565b915060c08801356137f78161378c565b8091505092959891949750929550565b60ff811681146111e657600080fd5b6000806040838503121561382957600080fd5b823561383481613807565b915060208301356138448161378c565b809150509250929050565b60008060006060848603121561386457600080fd5b833561386f81613807565b9250602084013561387f8161378c565b929592945050506040919091013590565b6000602082840312156138a257600080fd5b81356105ff81613807565b6000602082840312156138bf57600080fd5b5035919050565b6001600160a01b03811681146111e657600080fd5b600080604083850312156138ee57600080fd5b82356138f9816138c6565b91506020830135613844816138c6565b6000806020838503121561391c57600080fd5b823567ffffffffffffffff8082111561393457600080fd5b818501915085601f83011261394857600080fd5b81358181111561395757600080fd5b86602082850101111561396957600080fd5b60209290920196919550909350505050565b60005b8381101561399657818101518382015260200161397e565b838111156110335750506000910152565b600081518084526139bf81602086016020860161397b565b601f01601f19169290920160200192915050565b8215158152604060208201526000611d8e60408301846139a7565b600060208284031215613a0057600080fd5b81356105ff8161378c565b600080600060608486031215613a2057600080fd5b8335613a2b816138c6565b92506020840135613a3b816138c6565b91506040840135613a4b816138c6565b809150509250925092565b600060208284031215613a6857600080fd5b81356105ff816138c6565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613ad057600080fd5b5051919050565b80518015158114613ae757600080fd5b919050565b600060208284031215613afe57600080fd5b6105ff82613ad7565b600080600060608486031215613b1c57600080fd5b83359250602084013591506040840135613a4b81613807565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613b6557613b65613b35565b500290565b600082821015613b7c57613b7c613b35565b500390565b634e487b7160e01b600052603160045260246000fd5b60008219821115613baa57613baa613b35565b500190565b600063ffffffff808316818516808303821115613bce57613bce613b35565b01949350505050565b600063ffffffff83811690831681811015613bf457613bf4613b35565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff80841680613c2957613c29613bfc565b92169190910692915050565b634e487b7160e01b600052604160045260246000fd5b604051610240810167ffffffffffffffff81118282101715613c6f57613c6f613c35565b60405290565b6040805190810167ffffffffffffffff81118282101715613c6f57613c6f613c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715613cc157613cc1613c35565b604052919050565b8051613ae7816138c6565b8051613ae78161378c565b805160058110613ae757600080fd5b600067ffffffffffffffff821115613d0857613d08613c35565b5060051b60200190565b600082601f830112613d2357600080fd5b81516020613d38613d3383613cee565b613c98565b82815260059290921b84018101918181019086841115613d5757600080fd5b8286015b84811015613d7b578051613d6e816138c6565b8352918301918301613d5b565b509695505050505050565b600060208284031215613d9857600080fd5b815167ffffffffffffffff80821115613db057600080fd5b908301906102408286031215613dc557600080fd5b613dcd613c4b565b613dd683613cc9565b8152613de460208401613cc9565b6020820152613df560408401613cc9565b6040820152613e0660608401613cc9565b60608201526080838101519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a0613e78818501613cd4565b908201526101c0613e8a848201613cd4565b908201526101e0613e9c848201613cd4565b90820152610200613eae848201613cdf565b908201526102208381015183811115613ec657600080fd5b613ed288828701613d12565b918301919091525095945050505050565b60006020808385031215613ef657600080fd5b825167ffffffffffffffff80821115613f0e57600080fd5b9084019060408287031215613f2257600080fd5b613f2a613c75565b825160038110613f3957600080fd5b81528284015182811115613f4c57600080fd5b80840193505086601f840112613f6157600080fd5b825182811115613f7357613f73613c35565b613f85601f8201601f19168601613c98565b92508083528785828601011115613f9b57600080fd5b613faa8186850187870161397b565b5092830152509392505050565b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b838110156140065781516001600160a01b031687529582019590820190600101613fe1565b509495945050505050565b60006003871061402357614023613fb7565b86825260a0602083015261403a60a08301876139a7565b6001600160a01b0386811660408501528516606084015282810360808401526140638185613fcd565b98975050505050505050565b828152604081016004831061408657614086613fb7565b8260208301529392505050565b6000826140a2576140a2613bfc565b500490565b600060c082840312156140b957600080fd5b60405160c0810181811067ffffffffffffffff821117156140dc576140dc613c35565b60405282516140ea816138c6565b808252506020830151602082015260408301516040820152606083015161411081613807565b6060820152608083015161412381613807565b608082015261413460a08401613ad7565b60a08201529392505050565b828152604081016006831061408657614086613fb7565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000602082840312156141b457600080fd5b81516105ff81613807565b600181815b808511156141fa5781600019048211156141e0576141e0613b35565b808516156141ed57918102915b93841c93908002906141c4565b509250929050565b60008261421157506001610e2f565b8161421e57506000610e2f565b8160018114614234576002811461423e5761425a565b6001915050610e2f565b60ff84111561424f5761424f613b35565b50506001821b610e2f565b5060208310610133831016604e8410600b841016171561427d575081810a610e2f565b61428783836141bf565b806000190482111561429b5761429b613b35565b029392505050565b60006105ff60ff841683614202565b600063ffffffff808316818516818304811182151516156142d5576142d5613b35565b02949350505050565b805169ffffffffffffffffffff81168114613ae757600080fd5b600080600080600060a0868803121561431057600080fd5b614319866142de565b945060208601519350604086015192506060860151915061433c608087016142de565b90509295509295909350565b600060ff821660ff84168082101561436257614362613b35565b90039392505050565b60006105ff8383614202565b828152604060208201526000611d8e6040830184613fcd565b600060208083850312156143a357600080fd5b825167ffffffffffffffff8111156143ba57600080fd5b8301601f810185136143cb57600080fd5b80516143d9613d3382613cee565b81815260059190911b820183019083810190878311156143f857600080fd5b928401925b82841015613748578351825292840192908401906143fd565b85815284602082015260a06040820152600061443560a0830186613fcd565b6001600160a01b0394909416606083015250608001529392505050565b602081526000825160a0602084015261446e60c08401826139a7565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b6080815260006144bd6080830187613fcd565b60208301959095525060408101929092526001600160a01b0316606090910152919050565b600082516144f481846020870161397b565b9190910192915050565b6020815260006105ff60208301846139a756fea26469706673582212204d0d783e6a3a124d5ef08fda631f75a4ab828c5f3de7fae6c9113cdcb7072d9d64736f6c63430008090033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.