More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,354 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Multicall | 65639039 | 3 hrs ago | IN | 0 POL | 0.02841537 | ||||
Multicall | 65635201 | 5 hrs ago | IN | 0 POL | 0.05034984 | ||||
Multicall | 65627076 | 10 hrs ago | IN | 0 POL | 0.0155671 | ||||
Multicall | 65627069 | 10 hrs ago | IN | 0 POL | 0.01511153 | ||||
Multicall | 65626276 | 11 hrs ago | IN | 0 POL | 0.02828207 | ||||
Multicall | 65621274 | 14 hrs ago | IN | 0 POL | 0.00752684 | ||||
Multicall | 65570386 | 44 hrs ago | IN | 0 POL | 0.00771847 | ||||
Multicall | 65561279 | 2 days ago | IN | 0 POL | 0.01836443 | ||||
Multicall | 65555214 | 2 days ago | IN | 0 POL | 0.03159426 | ||||
Multicall | 65555091 | 2 days ago | IN | 0 POL | 0.03909069 | ||||
Multicall | 65485132 | 3 days ago | IN | 0 POL | 0.01478731 | ||||
Multicall | 65485128 | 3 days ago | IN | 0 POL | 0.01364863 | ||||
Multicall | 65480874 | 4 days ago | IN | 0 POL | 0.01244453 | ||||
Multicall | 65480854 | 4 days ago | IN | 0 POL | 0.01121838 | ||||
Multicall | 65475363 | 4 days ago | IN | 0 POL | 0.01239273 | ||||
Multicall | 65447370 | 4 days ago | IN | 0 POL | 0.01549788 | ||||
Multicall | 65447348 | 4 days ago | IN | 0 POL | 0.01549788 | ||||
Multicall | 65439205 | 5 days ago | IN | 0 POL | 0.01847505 | ||||
Multicall | 65425919 | 5 days ago | IN | 0 POL | 0.01761798 | ||||
Multicall | 65407700 | 5 days ago | IN | 0 POL | 0.01480656 | ||||
Multicall | 65405417 | 5 days ago | IN | 0 POL | 0.00723477 | ||||
Multicall | 65401455 | 6 days ago | IN | 0 POL | 0.00756508 | ||||
Multicall | 65377516 | 6 days ago | IN | 0 POL | 0.00953343 | ||||
Multicall | 65377487 | 6 days ago | IN | 0 POL | 0.01122431 | ||||
Multicall | 65359698 | 7 days ago | IN | 0 POL | 0.01594404 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
65621274 | 14 hrs ago | 2.06719758 POL | ||||
65621274 | 14 hrs ago | 2.06719758 POL | ||||
65570386 | 44 hrs ago | 1.50838273 POL | ||||
65570386 | 44 hrs ago | 1.50838273 POL | ||||
65475363 | 4 days ago | 0.01070931 POL | ||||
65475363 | 4 days ago | 0.01070931 POL | ||||
65439205 | 5 days ago | 1.69806647 POL | ||||
65439205 | 5 days ago | 1.69806647 POL | ||||
65401455 | 6 days ago | 0.11145412 POL | ||||
65401455 | 6 days ago | 0.11145412 POL | ||||
65351243 | 7 days ago | 0.07132469 POL | ||||
65351243 | 7 days ago | 0.07132469 POL | ||||
65320865 | 8 days ago | 45,500 POL | ||||
65267394 | 9 days ago | 2.12563288 POL | ||||
65267394 | 9 days ago | 2.12563288 POL | ||||
65264737 | 9 days ago | 2.23912145 POL | ||||
65264737 | 9 days ago | 2.23912145 POL | ||||
65188435 | 11 days ago | 0.1189382 POL | ||||
65188435 | 11 days ago | 0.1189382 POL | ||||
65148598 | 12 days ago | 3.34290103 POL | ||||
65148598 | 12 days ago | 3.34290103 POL | ||||
65146263 | 12 days ago | 0.65286175 POL | ||||
65146263 | 12 days ago | 0.65286175 POL | ||||
65122700 | 13 days ago | 55 POL | ||||
65073010 | 14 days ago | 5.25574651 POL |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DCAHubCompanion
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 9999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.22; import './DCAHubCompanionLibrariesHandler.sol'; import './DCAHubCompanionHubProxyHandler.sol'; import '../utils/BaseCompanion.sol'; contract DCAHubCompanion is DCAHubCompanionLibrariesHandler, DCAHubCompanionHubProxyHandler, BaseCompanion, IDCAHubCompanion { constructor( address _swapper, address _allowanceTarget, address _governor, IPermit2 _permit2 ) BaseCompanion(_swapper, _allowanceTarget, _governor, _permit2) {} }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import { IERC165 } from "./interfaces/external/IERC165.sol"; import { ISimulationAdapter } from "./interfaces/ISimulationAdapter.sol"; /** * @title Simulation Adapter * @author Sam Bugs * @notice This contracts adds off-chain simulation capabilities to existing contracts. It works similarly to a * multicall, but the state is not modified in each subcall. */ abstract contract SimulationAdapter is IERC165, ISimulationAdapter { /// @notice An error that contains a simulation's result error SimulatedCall(SimulationResult result); /// @inheritdoc IERC165 function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) { return _interfaceId == type(ISimulationAdapter).interfaceId || _interfaceId == type(IERC165).interfaceId; } /// @inheritdoc ISimulationAdapter function simulate(bytes[] calldata _calls) external payable returns (SimulationResult[] memory _results) { _results = new SimulationResult[](_calls.length); for (uint256 i = 0; i < _calls.length; i++) { _results[i] = _simulate(_calls[i]); } return _results; } /** * @notice Executes a simulation and returns the result * @param _call The call to simulate * @return _simulationResult The simulation's result */ function _simulate(bytes calldata _call) internal returns (SimulationResult memory _simulationResult) { (bool _success, bytes memory _result) = // solhint-disable-next-line avoid-low-level-calls address(this).delegatecall(abi.encodeWithSelector(this.simulateAndRevert.selector, _call)); require(!_success, "WTF? Should have failed!"); // Move pointer to ignore selector // solhint-disable-next-line no-inline-assembly assembly { _result := add(_result, 0x04) } (_simulationResult) = abi.decode(_result, (SimulationResult)); } /** * @notice Executes a call agains this contract and reverts with the result * @dev This is meant to be used internally, do not call! * @param _call The call to simulate */ function simulateAndRevert(bytes calldata _call) external payable { uint256 _gasAtStart = gasleft(); // solhint-disable-next-line avoid-low-level-calls (bool _success, bytes memory _result) = address(this).delegatecall(_call); uint256 _gasSpent = _gasAtStart - gasleft(); revert SimulatedCall(SimulationResult({ success: _success, result: _result, gasSpent: _gasSpent })); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; interface ISimulationAdapter { /// @notice A simulation's result struct SimulationResult { bool success; bytes result; uint256 gasSpent; } /** * @notice Executes individual simulations against this contract but doesn't modify the state when doing so * @dev This function is meant to be used for off-chain simulation and should not be called on-chain * @param calls The calls to simulate * @return results Each simulation result */ function simulate(bytes[] calldata calls) external payable returns (SimulationResult[] memory results); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; import '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol'; import '@mean-finance/oracles/solidity/interfaces/ITokenPriceOracle.sol'; import './IDCAPermissionManager.sol'; /** * @title The interface for all state related queries * @notice These methods allow users to read the hubs's current values */ interface IDCAHubParameters { /** * @notice Returns how much will the amount to swap differ from the previous swap. f.e. if the returned value is -100, then the amount to swap will be 100 less than the swap just before it * @dev `tokenA` must be smaller than `tokenB` (tokenA < tokenB) * @param tokenA One of the pair's token * @param tokenB The other of the pair's token * @param swapIntervalMask The byte representation of the swap interval to check * @param swapNumber The swap number to check * @return swapDeltaAToB How much less of token A will the following swap require * @return swapDeltaBToA How much less of token B will the following swap require */ function swapAmountDelta( address tokenA, address tokenB, bytes1 swapIntervalMask, uint32 swapNumber ) external view returns (uint128 swapDeltaAToB, uint128 swapDeltaBToA); /** * @notice Returns the sum of the ratios reported in all swaps executed until the given swap number * @dev `tokenA` must be smaller than `tokenB` (tokenA < tokenB) * @param tokenA One of the pair's token * @param tokenB The other of the pair's token * @param swapIntervalMask The byte representation of the swap interval to check * @param swapNumber The swap number to check * @return accumRatioAToB The sum of all ratios from A to B * @return accumRatioBToA The sum of all ratios from B to A */ function accumRatio( address tokenA, address tokenB, bytes1 swapIntervalMask, uint32 swapNumber ) external view returns (uint256 accumRatioAToB, uint256 accumRatioBToA); /** * @notice Returns swapping information about a specific pair * @dev `tokenA` must be smaller than `tokenB` (tokenA < tokenB) * @param tokenA One of the pair's token * @param tokenB The other of the pair's token * @param swapIntervalMask The byte representation of the swap interval to check * @return performedSwaps How many swaps have been executed * @return nextAmountToSwapAToB How much of token A will be swapped on the next swap * @return lastSwappedAt Timestamp of the last swap * @return nextAmountToSwapBToA How much of token B will be swapped on the next swap */ function swapData( address tokenA, address tokenB, bytes1 swapIntervalMask ) external view returns ( uint32 performedSwaps, uint224 nextAmountToSwapAToB, uint32 lastSwappedAt, uint224 nextAmountToSwapBToA ); /** * @notice Returns the byte representation of the set of actice swap intervals for the given pair * @dev `tokenA` must be smaller than `tokenB` (tokenA < tokenB) * @param tokenA The smaller of the pair's token * @param tokenB The other of the pair's token * @return The byte representation of the set of actice swap intervals */ function activeSwapIntervals(address tokenA, address tokenB) external view returns (bytes1); /** * @notice Returns how much of the hub's token balance belongs to the platform * @param token The token to check * @return The amount that belongs to the platform */ function platformBalance(address token) external view returns (uint256); } /** * @title The interface for all position related matters * @notice These methods allow users to create, modify and terminate their positions */ interface IDCAHubPositionHandler { /// @notice The position of a certain user struct UserPosition { // The token that the user deposited and will be swapped in exchange for "to" IERC20Metadata from; // The token that the user will get in exchange for their "from" tokens in each swap IERC20Metadata to; // How frequently the position's swaps should be executed uint32 swapInterval; // How many swaps were executed since deposit, last modification, or last withdraw uint32 swapsExecuted; // How many "to" tokens can currently be withdrawn uint256 swapped; // How many swaps left the position has to execute uint32 swapsLeft; // How many "from" tokens there are left to swap uint256 remaining; // How many "from" tokens need to be traded in each swap uint120 rate; } /// @notice A list of positions that all have the same `to` token struct PositionSet { // The `to` token address token; // The position ids uint256[] positionIds; } /** * @notice Emitted when a position is terminated * @param user The address of the user that terminated the position * @param recipientUnswapped The address of the user that will receive the unswapped tokens * @param recipientSwapped The address of the user that will receive the swapped tokens * @param positionId The id of the position that was terminated * @param returnedUnswapped How many "from" tokens were returned to the caller * @param returnedSwapped How many "to" tokens were returned to the caller */ event Terminated( address indexed user, address indexed recipientUnswapped, address indexed recipientSwapped, uint256 positionId, uint256 returnedUnswapped, uint256 returnedSwapped ); /** * @notice Emitted when a position is created * @param depositor The address of the user that creates the position * @param owner The address of the user that will own the position * @param positionId The id of the position that was created * @param fromToken The address of the "from" token * @param toToken The address of the "to" token * @param swapInterval How frequently the position's swaps should be executed * @param rate How many "from" tokens need to be traded in each swap * @param startingSwap The number of the swap when the position will be executed for the first time * @param lastSwap The number of the swap when the position will be executed for the last time * @param permissions The permissions defined for the position */ event Deposited( address indexed depositor, address indexed owner, uint256 positionId, address fromToken, address toToken, uint32 swapInterval, uint120 rate, uint32 startingSwap, uint32 lastSwap, IDCAPermissionManager.PermissionSet[] permissions ); /** * @notice Emitted when a position is created and extra data is provided * @param positionId The id of the position that was created * @param data The extra data that was provided */ event Miscellaneous(uint256 positionId, bytes data); /** * @notice Emitted when a user withdraws all swapped tokens from a position * @param withdrawer The address of the user that executed the withdraw * @param recipient The address of the user that will receive the withdrawn tokens * @param positionId The id of the position that was affected * @param token The address of the withdrawn tokens. It's the same as the position's "to" token * @param amount The amount that was withdrawn */ event Withdrew(address indexed withdrawer, address indexed recipient, uint256 positionId, address token, uint256 amount); /** * @notice Emitted when a user withdraws all swapped tokens from many positions * @param withdrawer The address of the user that executed the withdraws * @param recipient The address of the user that will receive the withdrawn tokens * @param positions The positions to withdraw from * @param withdrew The total amount that was withdrawn from each token */ event WithdrewMany(address indexed withdrawer, address indexed recipient, PositionSet[] positions, uint256[] withdrew); /** * @notice Emitted when a position is modified * @param user The address of the user that modified the position * @param positionId The id of the position that was modified * @param rate How many "from" tokens need to be traded in each swap * @param startingSwap The number of the swap when the position will be executed for the first time * @param lastSwap The number of the swap when the position will be executed for the last time */ event Modified(address indexed user, uint256 positionId, uint120 rate, uint32 startingSwap, uint32 lastSwap); /// @notice Thrown when a user tries to create a position with the same `from` & `to` error InvalidToken(); /// @notice Thrown when a user tries to create a position with a swap interval that is not allowed error IntervalNotAllowed(); /// @notice Thrown when a user tries operate on a position that doesn't exist (it might have been already terminated) error InvalidPosition(); /// @notice Thrown when a user tries operate on a position that they don't have access to error UnauthorizedCaller(); /// @notice Thrown when a user tries to create a position with zero swaps error ZeroSwaps(); /// @notice Thrown when a user tries to create a position with zero funds error ZeroAmount(); /// @notice Thrown when a user tries to withdraw a position whose `to` token doesn't match the specified one error PositionDoesNotMatchToken(); /// @notice Thrown when a user tries create or modify a position with an amount too big error AmountTooBig(); /** * @notice Returns the permission manager contract * @return The contract itself */ function permissionManager() external view returns (IDCAPermissionManager); /** * @notice Returns total created positions * @return The total created positions */ function totalCreatedPositions() external view returns (uint256); /** * @notice Returns a user position * @param positionId The id of the position * @return position The position itself */ function userPosition(uint256 positionId) external view returns (UserPosition memory position); /** * @notice Creates a new position * @dev Will revert: * - With ZeroAddress if from, to or owner are zero * - With InvalidToken if from == to * - With ZeroAmount if amount is zero * - With AmountTooBig if amount is too big * - With ZeroSwaps if amountOfSwaps is zero * - With IntervalNotAllowed if swapInterval is not allowed * @param from The address of the "from" token * @param to The address of the "to" token * @param amount How many "from" tokens will be swapped in total * @param amountOfSwaps How many swaps to execute for this position * @param swapInterval How frequently the position's swaps should be executed * @param owner The address of the owner of the position being created * @param permissions Extra permissions to add to the position. Can be empty * @return positionId The id of the created position */ function deposit( address from, address to, uint256 amount, uint32 amountOfSwaps, uint32 swapInterval, address owner, IDCAPermissionManager.PermissionSet[] calldata permissions ) external returns (uint256 positionId); /** * @notice Creates a new position * @dev Will revert: * - With ZeroAddress if from, to or owner are zero * - With InvalidToken if from == to * - With ZeroAmount if amount is zero * - With AmountTooBig if amount is too big * - With ZeroSwaps if amountOfSwaps is zero * - With IntervalNotAllowed if swapInterval is not allowed * @param from The address of the "from" token * @param to The address of the "to" token * @param amount How many "from" tokens will be swapped in total * @param amountOfSwaps How many swaps to execute for this position * @param swapInterval How frequently the position's swaps should be executed * @param owner The address of the owner of the position being created * @param permissions Extra permissions to add to the position. Can be empty * @param miscellaneous Bytes that will be emitted, and associated with the position * @return positionId The id of the created position */ function deposit( address from, address to, uint256 amount, uint32 amountOfSwaps, uint32 swapInterval, address owner, IDCAPermissionManager.PermissionSet[] calldata permissions, bytes calldata miscellaneous ) external returns (uint256 positionId); /** * @notice Withdraws all swapped tokens from a position to a recipient * @dev Will revert: * - With InvalidPosition if positionId is invalid * - With UnauthorizedCaller if the caller doesn't have access to the position * - With ZeroAddress if recipient is zero * @param positionId The position's id * @param recipient The address to withdraw swapped tokens to * @return swapped How much was withdrawn */ function withdrawSwapped(uint256 positionId, address recipient) external returns (uint256 swapped); /** * @notice Withdraws all swapped tokens from multiple positions * @dev Will revert: * - With InvalidPosition if any of the position ids are invalid * - With UnauthorizedCaller if the caller doesn't have access to the position to any of the given positions * - With ZeroAddress if recipient is zero * - With PositionDoesNotMatchToken if any of the positions do not match the token in their position set * @param positions A list positions, grouped by `to` token * @param recipient The address to withdraw swapped tokens to * @return withdrawn How much was withdrawn for each token */ function withdrawSwappedMany(PositionSet[] calldata positions, address recipient) external returns (uint256[] memory withdrawn); /** * @notice Takes the unswapped balance, adds the new deposited funds and modifies the position so that * it is executed in newSwaps swaps * @dev Will revert: * - With InvalidPosition if positionId is invalid * - With UnauthorizedCaller if the caller doesn't have access to the position * - With AmountTooBig if amount is too big * @param positionId The position's id * @param amount Amount of funds to add to the position * @param newSwaps The new amount of swaps */ function increasePosition( uint256 positionId, uint256 amount, uint32 newSwaps ) external; /** * @notice Withdraws the specified amount from the unswapped balance and modifies the position so that * it is executed in newSwaps swaps * @dev Will revert: * - With InvalidPosition if positionId is invalid * - With UnauthorizedCaller if the caller doesn't have access to the position * - With ZeroSwaps if newSwaps is zero and amount is not the total unswapped balance * @param positionId The position's id * @param amount Amount of funds to withdraw from the position * @param newSwaps The new amount of swaps * @param recipient The address to send tokens to */ function reducePosition( uint256 positionId, uint256 amount, uint32 newSwaps, address recipient ) external; /** * @notice Terminates the position and sends all unswapped and swapped balance to the specified recipients * @dev Will revert: * - With InvalidPosition if positionId is invalid * - With UnauthorizedCaller if the caller doesn't have access to the position * - With ZeroAddress if recipientUnswapped or recipientSwapped is zero * @param positionId The position's id * @param recipientUnswapped The address to withdraw unswapped tokens to * @param recipientSwapped The address to withdraw swapped tokens to * @return unswapped The unswapped balance sent to `recipientUnswapped` * @return swapped The swapped balance sent to `recipientSwapped` */ function terminate( uint256 positionId, address recipientUnswapped, address recipientSwapped ) external returns (uint256 unswapped, uint256 swapped); } /** * @title The interface for all swap related matters * @notice These methods allow users to get information about the next swap, and how to execute it */ interface IDCAHubSwapHandler { /// @notice Information about a swap struct SwapInfo { // The tokens involved in the swap TokenInSwap[] tokens; // The pairs involved in the swap PairInSwap[] pairs; } /// @notice Information about a token's role in a swap struct TokenInSwap { // The token's address address token; // How much will be given of this token as a reward uint256 reward; // How much of this token needs to be provided by swapper uint256 toProvide; // How much of this token will be paid to the platform uint256 platformFee; } /// @notice Information about a pair in a swap struct PairInSwap { // The address of one of the tokens address tokenA; // The address of the other token address tokenB; // The total amount of token A swapped in this pair uint256 totalAmountToSwapTokenA; // The total amount of token B swapped in this pair uint256 totalAmountToSwapTokenB; // How much is 1 unit of token A when converted to B uint256 ratioAToB; // How much is 1 unit of token B when converted to A uint256 ratioBToA; // The swap intervals involved in the swap, represented as a byte bytes1 intervalsInSwap; } /// @notice A pair of tokens, represented by their indexes in an array struct PairIndexes { // The index of the token A uint8 indexTokenA; // The index of the token B uint8 indexTokenB; } /** * @notice Emitted when a swap is executed * @param sender The address of the user that initiated the swap * @param rewardRecipient The address that received the reward * @param callbackHandler The address that executed the callback * @param swapInformation All information related to the swap * @param borrowed How much was borrowed * @param fee The swap fee at the moment of the swap */ event Swapped( address indexed sender, address indexed rewardRecipient, address indexed callbackHandler, SwapInfo swapInformation, uint256[] borrowed, uint32 fee ); /// @notice Thrown when pairs indexes are not sorted correctly error InvalidPairs(); /// @notice Thrown when trying to execute a swap, but there is nothing to swap error NoSwapsToExecute(); /** * @notice Returns all information related to the next swap * @dev Will revert with: * - With InvalidTokens if tokens are not sorted, or if there are duplicates * - With InvalidPairs if pairs are not sorted (first by indexTokenA and then indexTokenB), or if indexTokenA >= indexTokenB for any pair * @param tokens The tokens involved in the next swap * @param pairs The pairs that you want to swap. Each element of the list points to the index of the token in the tokens array * @param calculatePrivilegedAvailability Some accounts get privileged availability and can execute swaps before others. This flag provides * the possibility to calculate the next swap information for privileged and non-privileged accounts * @param oracleData Bytes to send to the oracle when executing a quote * @return swapInformation The information about the next swap */ function getNextSwapInfo( address[] calldata tokens, PairIndexes[] calldata pairs, bool calculatePrivilegedAvailability, bytes calldata oracleData ) external view returns (SwapInfo memory swapInformation); /** * @notice Executes a flash swap * @dev Will revert with: * - With InvalidTokens if tokens are not sorted, or if there are duplicates * - With InvalidPairs if pairs are not sorted (first by indexTokenA and then indexTokenB), or if indexTokenA >= indexTokenB for any pair * - With Paused if swaps are paused by protocol * - With NoSwapsToExecute if there are no swaps to execute for the given pairs * - With LiquidityNotReturned if the required tokens were not back during the callback * @param tokens The tokens involved in the next swap * @param pairsToSwap The pairs that you want to swap. Each element of the list points to the index of the token in the tokens array * @param rewardRecipient The address to send the reward to * @param callbackHandler Address to call for callback (and send the borrowed tokens to) * @param borrow How much to borrow of each of the tokens in tokens. The amount must match the position of the token in the tokens array * @param callbackData Bytes to send to the caller during the callback * @param oracleData Bytes to send to the oracle when executing a quote * @return Information about the executed swap */ function swap( address[] calldata tokens, PairIndexes[] calldata pairsToSwap, address rewardRecipient, address callbackHandler, uint256[] calldata borrow, bytes calldata callbackData, bytes calldata oracleData ) external returns (SwapInfo memory); } /** * @title The interface for handling all configuration * @notice This contract will manage configuration that affects all pairs, swappers, etc */ interface IDCAHubConfigHandler { /** * @notice Emitted when a new oracle is set * @param oracle The new oracle contract */ event OracleSet(ITokenPriceOracle oracle); /** * @notice Emitted when a new swap fee is set * @param feeSet The new swap fee */ event SwapFeeSet(uint32 feeSet); /** * @notice Emitted when new swap intervals are allowed * @param swapIntervals The new swap intervals */ event SwapIntervalsAllowed(uint32[] swapIntervals); /** * @notice Emitted when some swap intervals are no longer allowed * @param swapIntervals The swap intervals that are no longer allowed */ event SwapIntervalsForbidden(uint32[] swapIntervals); /** * @notice Emitted when a new platform fee ratio is set * @param platformFeeRatio The new platform fee ratio */ event PlatformFeeRatioSet(uint16 platformFeeRatio); /** * @notice Emitted when allowed states of tokens are updated * @param tokens Array of updated tokens * @param allowed Array of new allow state per token were allowed[i] is the updated state of tokens[i] */ event TokensAllowedUpdated(address[] tokens, bool[] allowed); /// @notice Thrown when trying to interact with an unallowed token error UnallowedToken(); /// @notice Thrown when set allowed tokens input is not valid error InvalidAllowedTokensInput(); /// @notice Thrown when trying to set a fee higher than the maximum allowed error HighFee(); /// @notice Thrown when trying to set a fee that is not multiple of 100 error InvalidFee(); /// @notice Thrown when trying to set a fee ratio that is higher that the maximum allowed error HighPlatformFeeRatio(); /** * @notice Returns the max fee ratio that can be set * @dev Cannot be modified * @return The maximum possible value */ // solhint-disable-next-line func-name-mixedcase function MAX_PLATFORM_FEE_RATIO() external view returns (uint16); /** * @notice Returns the fee charged on swaps * @return swapFee The fee itself */ function swapFee() external view returns (uint32 swapFee); /** * @notice Returns the price oracle contract * @return oracle The contract itself */ function oracle() external view returns (ITokenPriceOracle oracle); /** * @notice Returns how much will the platform take from the fees collected in swaps * @return The current ratio */ function platformFeeRatio() external view returns (uint16); /** * @notice Returns the max fee that can be set for swaps * @dev Cannot be modified * @return maxFee The maximum possible fee */ // solhint-disable-next-line func-name-mixedcase function MAX_FEE() external view returns (uint32 maxFee); /** * @notice Returns a byte that represents allowed swap intervals * @return allowedSwapIntervals The allowed swap intervals */ function allowedSwapIntervals() external view returns (bytes1 allowedSwapIntervals); /** * @notice Returns if a token is currently allowed or not * @return Allowed state of token */ function allowedTokens(address token) external view returns (bool); /** * @notice Returns token's magnitude (10**decimals) * @return Stored magnitude for token */ function tokenMagnitude(address token) external view returns (uint120); /** * @notice Returns whether swaps and deposits are currently paused * @return isPaused Whether swaps and deposits are currently paused */ function paused() external view returns (bool isPaused); /** * @notice Sets a new swap fee * @dev Will revert with HighFee if the fee is higher than the maximum * @dev Will revert with InvalidFee if the fee is not multiple of 100 * @param fee The new swap fee */ function setSwapFee(uint32 fee) external; /** * @notice Sets a new price oracle * @dev Will revert with ZeroAddress if the zero address is passed * @param oracle The new oracle contract */ function setOracle(ITokenPriceOracle oracle) external; /** * @notice Sets a new platform fee ratio * @dev Will revert with HighPlatformFeeRatio if given ratio is too high * @param platformFeeRatio The new ratio */ function setPlatformFeeRatio(uint16 platformFeeRatio) external; /** * @notice Adds new swap intervals to the allowed list * @param swapIntervals The new swap intervals */ function addSwapIntervalsToAllowedList(uint32[] calldata swapIntervals) external; /** * @notice Removes some swap intervals from the allowed list * @param swapIntervals The swap intervals to remove */ function removeSwapIntervalsFromAllowedList(uint32[] calldata swapIntervals) external; /// @notice Pauses all swaps and deposits function pause() external; /// @notice Unpauses all swaps and deposits function unpause() external; } /** * @title The interface for handling platform related actions * @notice This contract will handle all actions that affect the platform in some way */ interface IDCAHubPlatformHandler { /** * @notice Emitted when someone withdraws from the paltform balance * @param sender The address of the user that initiated the withdraw * @param recipient The address that received the withdraw * @param amounts The tokens (and the amount) that were withdrawn */ event WithdrewFromPlatform(address indexed sender, address indexed recipient, IDCAHub.AmountOfToken[] amounts); /** * @notice Withdraws tokens from the platform balance * @param amounts The amounts to withdraw * @param recipient The address that will receive the tokens */ function withdrawFromPlatformBalance(IDCAHub.AmountOfToken[] calldata amounts, address recipient) external; } interface IDCAHub is IDCAHubParameters, IDCAHubConfigHandler, IDCAHubSwapHandler, IDCAHubPositionHandler, IDCAHubPlatformHandler { /// @notice Specifies an amount of a token. For example to determine how much to borrow from certain tokens struct AmountOfToken { // The tokens' address address token; // How much to borrow or withdraw of the specified token uint256 amount; } /// @notice Thrown when one of the parameters is a zero address error ZeroAddress(); /// @notice Thrown when the expected liquidity is not returned in flash swaps error LiquidityNotReturned(); /// @notice Thrown when a list of token pairs is not sorted, or if there are duplicates error InvalidTokens(); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import '@mean-finance/nft-descriptors/solidity/interfaces/IDCAHubPositionDescriptor.sol'; interface IERC721BasicEnumerable { /** * @notice Count NFTs tracked by this contract * @return A count of valid NFTs tracked by this contract, where each one of * them has an assigned and queryable owner not equal to the zero address */ function totalSupply() external view returns (uint256); } /** * @title The interface for all permission related matters * @notice These methods allow users to set and remove permissions to their positions */ interface IDCAPermissionManager is IERC721, IERC721BasicEnumerable { /// @notice Set of possible permissions enum Permission { INCREASE, REDUCE, WITHDRAW, TERMINATE } /// @notice A set of permissions for a specific operator struct PermissionSet { // The address of the operator address operator; // The permissions given to the overator Permission[] permissions; } /// @notice A collection of permissions sets for a specific position struct PositionPermissions { // The id of the token uint256 tokenId; // The permissions to assign to the position PermissionSet[] permissionSets; } /** * @notice Emitted when permissions for a token are modified * @param tokenId The id of the token * @param permissions The set of permissions that were updated */ event Modified(uint256 tokenId, PermissionSet[] permissions); /** * @notice Emitted when the address for a new descritor is set * @param descriptor The new descriptor contract */ event NFTDescriptorSet(IDCAHubPositionDescriptor descriptor); /// @notice Thrown when a user tries to set the hub, once it was already set error HubAlreadySet(); /// @notice Thrown when a user provides a zero address when they shouldn't error ZeroAddress(); /// @notice Thrown when a user calls a method that can only be executed by the hub error OnlyHubCanExecute(); /// @notice Thrown when a user tries to modify permissions for a token they do not own error NotOwner(); /// @notice Thrown when a user tries to execute a permit with an expired deadline error ExpiredDeadline(); /// @notice Thrown when a user tries to execute a permit with an invalid signature error InvalidSignature(); /** * @notice The permit typehash used in the permit signature * @return The typehash for the permit */ // solhint-disable-next-line func-name-mixedcase function PERMIT_TYPEHASH() external pure returns (bytes32); /** * @notice The permit typehash used in the permission permit signature * @return The typehash for the permission permit */ // solhint-disable-next-line func-name-mixedcase function PERMISSION_PERMIT_TYPEHASH() external pure returns (bytes32); /** * @notice The permit typehash used in the multi permission permit signature * @return The typehash for the multi permission permit */ // solhint-disable-next-line func-name-mixedcase function MULTI_PERMISSION_PERMIT_TYPEHASH() external pure returns (bytes32); /** * @notice The permit typehash used in the permission permit signature * @return The typehash for the permission set */ // solhint-disable-next-line func-name-mixedcase function PERMISSION_SET_TYPEHASH() external pure returns (bytes32); /** * @notice The permit typehash used in the multi permission permit signature * @return The typehash for the position permissions */ // solhint-disable-next-line func-name-mixedcase function POSITION_PERMISSIONS_TYPEHASH() external pure returns (bytes32); /** * @notice The domain separator used in the permit signature * @return The domain seperator used in encoding of permit signature */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); /** * @notice Returns the NFT descriptor contract * @return The contract for the NFT descriptor */ function nftDescriptor() external returns (IDCAHubPositionDescriptor); /** * @notice Returns the address of the DCA Hub * @return The address of the DCA Hub */ function hub() external returns (address); /** * @notice Returns the next nonce to use for a given user * @param user The address of the user * @return nonce The next nonce to use */ function nonces(address user) external returns (uint256 nonce); /** * @notice Returns whether the given address has the permission for the given token * @param id The id of the token to check * @param account The address of the user to check * @param permission The permission to check * @return Whether the user has the permission or not */ function hasPermission( uint256 id, address account, Permission permission ) external view returns (bool); /** * @notice Returns whether the given address has the permissions for the given token * @param id The id of the token to check * @param account The address of the user to check * @param permissions The permissions to check * @return hasPermissions Whether the user has each permission or not */ function hasPermissions( uint256 id, address account, Permission[] calldata permissions ) external view returns (bool[] memory hasPermissions); /** * @notice Sets the address for the hub * @dev Can only be successfully executed once. Once it's set, it can be modified again * Will revert: * - With ZeroAddress if address is zero * - With HubAlreadySet if the hub has already been set * @param hub The address to set for the hub */ function setHub(address hub) external; /** * @notice Mints a new NFT with the given id, and sets the permissions for it * @dev Will revert with OnlyHubCanExecute if the caller is not the hub * @param id The id of the new NFT * @param owner The owner of the new NFT * @param permissions Permissions to set for the new NFT */ function mint( uint256 id, address owner, PermissionSet[] calldata permissions ) external; /** * @notice Burns the NFT with the given id, and clears all permissions * @dev Will revert with OnlyHubCanExecute if the caller is not the hub * @param id The token's id */ function burn(uint256 id) external; /** * @notice Sets new permissions for the given position * @dev Will revert with NotOwner if the caller is not the token's owner. * Operators that are not part of the given permission sets do not see their permissions modified. * In order to remove permissions to an operator, provide an empty list of permissions for them * @param id The token's id * @param permissions A list of permission sets */ function modify(uint256 id, PermissionSet[] calldata permissions) external; /** * @notice Sets new permissions for the given positions * @dev This is basically the same as executing multiple `modify` * @param permissions A list of position permissions to set */ function modifyMany(PositionPermissions[] calldata permissions) external; /** * @notice Approves spending of a specific token ID by spender via signature * @param spender The account that is being approved * @param tokenId The ID of the token that is being approved for spending * @param deadline The deadline timestamp by which the call must be mined for the approve to work * @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` * @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` * @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` */ function permit( address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @notice Sets permissions via signature * @dev This method works similarly to `modifyMany`, but instead of being executed by the owner, it can be set by signature * @param permissions The permissions to set for the different positions * @param deadline The deadline timestamp by which the call must be mined for the approve to work * @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` * @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` * @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` */ function multiPermissionPermit( PositionPermissions[] calldata permissions, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @notice Sets permissions via signature * @dev This method works similarly to `modify`, but instead of being executed by the owner, it can be set my signature * @param permissions The permissions to set * @param tokenId The token's id * @param deadline The deadline timestamp by which the call must be mined for the approve to work * @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` * @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` * @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` */ function permissionPermit( PermissionSet[] calldata permissions, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @notice Sets a new NFT descriptor * @dev Will revert with ZeroAddress if address is zero * @param descriptor The new NFT descriptor contract */ function setNFTDescriptor(IDCAHubPositionDescriptor descriptor) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; /// @title Intervals library /// @notice Provides functions to easily convert from swap intervals to their byte representation and viceversa library Intervals { /// @notice Thrown when a user tries convert and invalid interval to a byte representation error InvalidInterval(); /// @notice Thrown when a user tries convert and invalid byte representation to an interval error InvalidMask(); /// @notice Takes a swap interval and returns its byte representation /// @dev Will revert with InvalidInterval if the swap interval is not valid /// @param _swapInterval The swap interval /// @return The interval's byte representation function intervalToMask(uint32 _swapInterval) internal pure returns (bytes1) { if (_swapInterval == 1 minutes) return 0x01; if (_swapInterval == 5 minutes) return 0x02; if (_swapInterval == 15 minutes) return 0x04; if (_swapInterval == 30 minutes) return 0x08; if (_swapInterval == 1 hours) return 0x10; if (_swapInterval == 4 hours) return 0x20; if (_swapInterval == 1 days) return 0x40; if (_swapInterval == 1 weeks) return 0x80; revert InvalidInterval(); } /// @notice Takes a byte representation of a swap interval and returns the swap interval /// @dev Will revert with InvalidMask if the byte representation is not valid /// @param _mask The byte representation /// @return The swap interval function maskToInterval(bytes1 _mask) internal pure returns (uint32) { if (_mask == 0x01) return 1 minutes; if (_mask == 0x02) return 5 minutes; if (_mask == 0x04) return 15 minutes; if (_mask == 0x08) return 30 minutes; if (_mask == 0x10) return 1 hours; if (_mask == 0x20) return 4 hours; if (_mask == 0x40) return 1 days; if (_mask == 0x80) return 1 weeks; revert InvalidMask(); } /// @notice Takes a byte representation of a set of swap intervals and returns which ones are in the set /// @dev Will always return an array of length 8, with zeros at the end if there are less than 8 intervals /// @param _byte The byte representation /// @return _intervals The swap intervals in the set function intervalsInByte(bytes1 _byte) internal pure returns (uint32[] memory _intervals) { _intervals = new uint32[](8); uint8 _index; bytes1 _mask = 0x01; while (_byte >= _mask && _mask > 0) { if (_byte & _mask != 0) { _intervals[_index++] = maskToInterval(_mask); } _mask <<= 1; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >0.6; /// @title TokenSorting library /// @notice Provides functions to sort tokens easily library TokenSorting { /// @notice Takes two tokens, and returns them sorted /// @param _tokenA One of the tokens /// @param _tokenB The other token /// @return __tokenA The first of the tokens /// @return __tokenB The second of the tokens function sortTokens(address _tokenA, address _tokenB) internal pure returns (address __tokenA, address __tokenB) { (__tokenA, __tokenB) = _tokenA < _tokenB ? (_tokenA, _tokenB) : (_tokenB, _tokenA); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.22; import '../interfaces/IDCAHubCompanion.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; /// @dev All public functions are payable, so that they can be multicalled together with other payable functions when msg.value > 0 abstract contract DCAHubCompanionHubProxyHandler is IDCAHubCompanionHubProxyHandler { using SafeERC20 for IERC20; /// @inheritdoc IDCAHubCompanionHubProxyHandler function permissionPermit( IDCAPermissionManager _permissionManager, IDCAPermissionManager.PermissionSet[] calldata _permissions, uint256 _tokenId, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external payable { _permissionManager.permissionPermit(_permissions, _tokenId, _deadline, _v, _r, _s); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function multiPermissionPermit( IDCAPermissionManager _permissionManager, IDCAPermissionManager.PositionPermissions[] calldata _permissions, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external payable { _permissionManager.multiPermissionPermit(_permissions, _deadline, _v, _r, _s); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function deposit( IDCAHub _hub, address _from, address _to, uint256 _amount, uint32 _amountOfSwaps, uint32 _swapInterval, address _owner, IDCAPermissionManager.PermissionSet[] calldata _permissions, bytes calldata _miscellaneous ) public payable virtual returns (uint256 _positionId) { _approveHub(address(_from), _hub, _amount); _positionId = _miscellaneous.length > 0 ? _hub.deposit(_from, _to, _amount, _amountOfSwaps, _swapInterval, _owner, _permissions, _miscellaneous) : _hub.deposit(_from, _to, _amount, _amountOfSwaps, _swapInterval, _owner, _permissions); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function depositWithBalanceOnContract( IDCAHub _hub, address _from, address _to, uint32 _amountOfSwaps, uint32 _swapInterval, address _owner, IDCAPermissionManager.PermissionSet[] calldata _permissions, bytes calldata _miscellaneous ) external payable returns (uint256 _positionId) { uint256 _amount = IERC20(_from).balanceOf(address(this)); return deposit(_hub, _from, _to, _amount, _amountOfSwaps, _swapInterval, _owner, _permissions, _miscellaneous); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function withdrawSwapped( IDCAHub _hub, uint256 _positionId, address _recipient ) external payable verifyPermission(_hub, _positionId, IDCAPermissionManager.Permission.WITHDRAW) returns (uint256 _swapped) { _swapped = _hub.withdrawSwapped(_positionId, _recipient); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function withdrawSwappedMany( IDCAHub _hub, IDCAHub.PositionSet[] calldata _positions, address _recipient ) external payable returns (uint256[] memory _withdrawn) { for (uint256 i = 0; i < _positions.length; ++i) { uint256[] memory _positionIds = _positions[i].positionIds; for (uint256 j = 0; j < _positionIds.length; ++j) { _checkPermissionOrFail(_hub, _positionIds[j], IDCAPermissionManager.Permission.WITHDRAW); } } _withdrawn = _hub.withdrawSwappedMany(_positions, _recipient); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function increasePosition( IDCAHub _hub, uint256 _positionId, uint256 _amount, uint32 _newSwaps ) external payable verifyPermission(_hub, _positionId, IDCAPermissionManager.Permission.INCREASE) { IERC20Metadata _from = _hub.userPosition(_positionId).from; _approveHub(address(_from), _hub, _amount); _hub.increasePosition(_positionId, _amount, _newSwaps); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function increasePositionWithBalanceOnContract( IDCAHub _hub, uint256 _positionId, uint32 _newSwaps ) external payable verifyPermission(_hub, _positionId, IDCAPermissionManager.Permission.INCREASE) { IERC20Metadata _from = _hub.userPosition(_positionId).from; uint256 _amount = _from.balanceOf(address(this)); _approveHub(address(_from), _hub, _amount); _hub.increasePosition(_positionId, _amount, _newSwaps); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function reducePosition( IDCAHub _hub, uint256 _positionId, uint256 _amount, uint32 _newSwaps, address _recipient ) external payable verifyPermission(_hub, _positionId, IDCAPermissionManager.Permission.REDUCE) { _hub.reducePosition(_positionId, _amount, _newSwaps, _recipient); } /// @inheritdoc IDCAHubCompanionHubProxyHandler function terminate( IDCAHub _hub, uint256 _positionId, address _recipientUnswapped, address _recipientSwapped ) external payable verifyPermission(_hub, _positionId, IDCAPermissionManager.Permission.TERMINATE) returns (uint256 _unswapped, uint256 _swapped) { (_unswapped, _swapped) = _hub.terminate(_positionId, _recipientUnswapped, _recipientSwapped); } function _approveHub( address _token, IDCAHub _hub, uint256 _amount ) internal { uint256 _allowance = IERC20(_token).allowance(address(this), address(_hub)); if (_allowance < _amount) { IERC20(_token).forceApprove(address(_hub), type(uint256).max); } } function _checkPermissionOrFail( IDCAHub _hub, uint256 _positionId, IDCAPermissionManager.Permission _permission ) internal view { if (!_hub.permissionManager().hasPermission(_positionId, msg.sender, _permission)) revert UnauthorizedCaller(); } modifier verifyPermission( IDCAHub _hub, uint256 _positionId, IDCAPermissionManager.Permission _permission ) { _checkPermissionOrFail(_hub, _positionId, _permission); _; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.22; import '../libraries/InputBuilding.sol'; import '../libraries/SecondsUntilNextSwap.sol'; import '../interfaces/IDCAHubCompanion.sol'; abstract contract DCAHubCompanionLibrariesHandler is IDCAHubCompanionLibrariesHandler { /// @inheritdoc IDCAHubCompanionLibrariesHandler function getNextSwapInfo( IDCAHub _hub, Pair[] calldata _pairs, bool _calculatePrivilegedAvailability, bytes calldata _oracleData ) external view returns (IDCAHub.SwapInfo memory) { (address[] memory _tokens, IDCAHub.PairIndexes[] memory _indexes) = InputBuilding.buildGetNextSwapInfoInput(_pairs); return _hub.getNextSwapInfo(_tokens, _indexes, _calculatePrivilegedAvailability, _oracleData); } /// @inheritdoc IDCAHubCompanionLibrariesHandler function legacyGetNextSwapInfo(ILegacyDCAHub _hub, Pair[] calldata _pairs) external view returns (ILegacyDCAHub.SwapInfo memory) { (address[] memory _tokens, IDCAHub.PairIndexes[] memory _indexes) = InputBuilding.buildGetNextSwapInfoInput(_pairs); return _hub.getNextSwapInfo(_tokens, _indexes); } /// @inheritdoc IDCAHubCompanionLibrariesHandler function secondsUntilNextSwap( IDCAHub _hub, Pair[] calldata _pairs, bool _calculatePrivilegedAvailability ) external view returns (uint256[] memory) { return SecondsUntilNextSwap.secondsUntilNextSwap(_hub, _pairs, _calculatePrivilegedAvailability); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7; import '@mean-finance/dca-v2-core/contracts/interfaces/IDCAHub.sol'; import '@mean-finance/dca-v2-core/contracts/interfaces/IDCAPermissionManager.sol'; import './ILegacyDCAHub.sol'; import './ISharedTypes.sol'; /** * @notice This contract exposes many utils that are also available through libraries. The idea is to make * these functions available here, so others don't need to deploy new contracts */ interface IDCAHubCompanionLibrariesHandler { /** * @notice Takes a list of pairs and returns how it would look like to execute a swap for all of them * @dev Please note that this function is very expensive. Ideally, it would be used for off-chain purposes * @param hub The address of the DCAHub * @param pairs The pairs to be involved in the swap * @param calculatePrivilegedAvailability Some accounts get privileged availability and can execute swaps before others. This flag provides * the possibility to calculate the next swap information for privileged and non-privileged accounts * @param oracleData Bytes to send to the oracle when executing a quote * @return How executing a swap for all the given pairs would look like */ function getNextSwapInfo( IDCAHub hub, Pair[] calldata pairs, bool calculatePrivilegedAvailability, bytes calldata oracleData ) external view returns (IDCAHub.SwapInfo memory); /** * @notice Takes a list of pairs and returns how it would look like to execute a swap for all of them * @dev Please note that this function is very expensive. Ideally, it would be used for off-chain purposes * @param hub The address of the DCAHub * @param pairs The pairs to be involved in the swap * @return How executing a swap for all the given pairs would look like */ function legacyGetNextSwapInfo(ILegacyDCAHub hub, Pair[] calldata pairs) external view returns (ILegacyDCAHub.SwapInfo memory); /** * @notice Returns how many seconds left until the next swap is available for a list of pairs * @dev Tokens in pairs may be passed in either tokenA/tokenB or tokenB/tokenA order * @param hub The address of the DCAHub * @param pairs Pairs to check * @param calculatePrivilegedAvailability Some accounts get privileged availability and can execute swaps before others. This flag provides * the possibility to calculate the seconds until next swap for privileged and non-privileged accounts * @return The amount of seconds until next swap for each of the pairs */ function secondsUntilNextSwap( IDCAHub hub, Pair[] calldata pairs, bool calculatePrivilegedAvailability ) external view returns (uint256[] memory); } interface IDCAHubCompanionHubProxyHandler { /// @notice Thrown when a user tries operate on a position that they don't have access to error UnauthorizedCaller(); /** * @notice Creates a new position * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param from The address of the "from" token * @param to The address of the "to" token * @param amount How many "from" tokens will be swapped in total * @param amountOfSwaps How many swaps to execute for this position * @param swapInterval How frequently the position's swaps should be executed * @param owner The address of the owner of the position being created * @param miscellaneous Bytes that will be emitted, and associated with the position. If empty, no event will be emitted * @return positionId The id of the created position */ function deposit( IDCAHub hub, address from, address to, uint256 amount, uint32 amountOfSwaps, uint32 swapInterval, address owner, IDCAPermissionManager.PermissionSet[] calldata permissions, bytes calldata miscellaneous ) external payable returns (uint256 positionId); /** * @notice Creates a new position using the entire balance available on the contract * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param from The address of the "from" token * @param to The address of the "to" token * @param amountOfSwaps How many swaps to execute for this position * @param swapInterval How frequently the position's swaps should be executed * @param owner The address of the owner of the position being created * @param miscellaneous Bytes that will be emitted, and associated with the position. If empty, no event will be emitted * @return positionId The id of the created position */ function depositWithBalanceOnContract( IDCAHub hub, address from, address to, uint32 amountOfSwaps, uint32 swapInterval, address owner, IDCAPermissionManager.PermissionSet[] calldata permissions, bytes calldata miscellaneous ) external payable returns (uint256 positionId); /** * @notice Call the hub and withdraws all swapped tokens from a position to a recipient * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positionId The position's id * @param recipient The address to withdraw swapped tokens to * @return swapped How much was withdrawn */ function withdrawSwapped( IDCAHub hub, uint256 positionId, address recipient ) external payable returns (uint256 swapped); /** * @notice Call the hub and withdraws all swapped tokens from multiple positions * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positions A list positions, grouped by `to` token * @param recipient The address to withdraw swapped tokens to * @return withdrawn How much was withdrawn for each token */ function withdrawSwappedMany( IDCAHub hub, IDCAHub.PositionSet[] calldata positions, address recipient ) external payable returns (uint256[] memory withdrawn); /** * @notice Call the hub and takes the unswapped balance, adds the new deposited funds and modifies the position so that * it is executed in `newSwaps` swaps * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positionId The position's id * @param amount Amount of funds to add to the position * @param newSwaps The new amount of swaps */ function increasePosition( IDCAHub hub, uint256 positionId, uint256 amount, uint32 newSwaps ) external payable; /** * @notice Call the hub and takes the unswapped balance, adds the Companion's current balance and modifies the position so that * it is executed in `newSwaps` swaps * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positionId The position's id * @param newSwaps The new amount of swaps */ function increasePositionWithBalanceOnContract( IDCAHub hub, uint256 positionId, uint32 newSwaps ) external payable; /** * @notice Call the hub and withdraws the specified amount from the unswapped balance and modifies the position so that * it is executed in newSwaps swaps * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positionId The position's id * @param amount Amount of funds to withdraw from the position * @param newSwaps The new amount of swaps * @param recipient The address to send tokens to */ function reducePosition( IDCAHub hub, uint256 positionId, uint256 amount, uint32 newSwaps, address recipient ) external payable; /** * @notice Calls the hub and terminates the position and sends all unswapped and swapped balance to the specified recipients * @dev Meant to be used as part of a multicall * @param hub The address of the DCAHub * @param positionId The position's id * @param recipientUnswapped The address to withdraw unswapped tokens to * @param recipientSwapped The address to withdraw swapped tokens to * @return unswapped The unswapped balance sent to `recipientUnswapped` * @return swapped The swapped balance sent to `recipientSwapped` */ function terminate( IDCAHub hub, uint256 positionId, address recipientUnswapped, address recipientSwapped ) external payable returns (uint256 unswapped, uint256 swapped); /** * @notice Calls the permission manager and sets multiple permissions via signature * @param permissionManager The address of the permission manager * @param permissions The permissions to set * @param deadline The deadline timestamp by which the call must be mined for the approve to work * @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` * @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` * @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` */ function multiPermissionPermit( IDCAPermissionManager permissionManager, IDCAPermissionManager.PositionPermissions[] calldata permissions, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; /** * @notice Calls the permission manager and sets permissions via signature * @param permissionManager The address of the permission manager * @param permissions The permissions to set * @param tokenId The token's id * @param deadline The deadline timestamp by which the call must be mined for the approve to work * @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` * @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` * @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` */ function permissionPermit( IDCAPermissionManager permissionManager, IDCAPermissionManager.PermissionSet[] calldata permissions, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; } interface IDCAHubCompanion is IDCAHubCompanionLibrariesHandler, IDCAHubCompanionHubProxyHandler {}
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7; import '@mean-finance/dca-v2-core/contracts/interfaces/IDCAHub.sol'; interface ILegacyDCAHub { /// @notice Information about a swap struct SwapInfo { // The tokens involved in the swap TokenInSwap[] tokens; // The pairs involved in the swap PairInSwap[] pairs; } /// @notice Information about a token's role in a swap struct TokenInSwap { // The token's address address token; // How much will be given of this token as a reward uint256 reward; // How much of this token needs to be provided by swapper uint256 toProvide; // How much of this token will be paid to the platform uint256 platformFee; } /// @notice Information about a pair in a swap struct PairInSwap { // The address of one of the tokens address tokenA; // The address of the other token address tokenB; // How much is 1 unit of token A when converted to B uint256 ratioAToB; // How much is 1 unit of token B when converted to A uint256 ratioBToA; // The swap intervals involved in the swap, represented as a byte bytes1 intervalsInSwap; } /** * @notice Returns all information related to the next swap * @dev Will revert with: * - With InvalidTokens if tokens are not sorted, or if there are duplicates * - With InvalidPairs if pairs are not sorted (first by indexTokenA and then indexTokenB), or if indexTokenA >= indexTokenB for any pair * @param tokens The tokens involved in the next swap * @param pairs The pairs that you want to swap. Each element of the list points to the index of the token in the tokens array * @return swapInformation The information about the next swap */ function getNextSwapInfo(address[] calldata tokens, IDCAHub.PairIndexes[] calldata pairs) external view returns (SwapInfo memory swapInformation); /** * @notice Executes a flash swap * @dev Will revert with: * - With InvalidTokens if tokens are not sorted, or if there are duplicates * - With InvalidPairs if pairs are not sorted (first by indexTokenA and then indexTokenB), or if indexTokenA >= indexTokenB for any pair * - With Paused if swaps are paused by protocol * - With NoSwapsToExecute if there are no swaps to execute for the given pairs * - With LiquidityNotReturned if the required tokens were not back during the callback * @param tokens The tokens involved in the next swap * @param pairsToSwap The pairs that you want to swap. Each element of the list points to the index of the token in the tokens array * @param rewardRecipient The address to send the reward to * @param callbackHandler Address to call for callback (and send the borrowed tokens to) * @param borrow How much to borrow of each of the tokens in tokens. The amount must match the position of the token in the tokens array * @param callbackData Bytes to send to the caller during the callback * @return Information about the executed swap */ function swap( address[] calldata tokens, IDCAHub.PairIndexes[] calldata pairsToSwap, address rewardRecipient, address callbackHandler, uint256[] calldata borrow, bytes calldata callbackData ) external returns (SwapInfo memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7; /// @notice A pair of tokens struct Pair { address tokenA; address tokenB; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Minimal Permit2 interface, derived from // https://github.com/Uniswap/permit2/blob/main/src/interfaces/ISignatureTransfer.sol interface IPermit2 { struct TokenPermissions { address token; uint256 amount; } struct PermitTransferFrom { TokenPermissions permitted; uint256 nonce; uint256 deadline; } struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; } struct SignatureTransferDetails { address to; uint256 requestedAmount; } // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); function permitTransferFrom( PermitTransferFrom calldata permit, SignatureTransferDetails calldata transferDetails, address owner, bytes calldata signature ) external; function permitTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes calldata signature ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7; import '@mean-finance/dca-v2-core/contracts/interfaces/IDCAHub.sol'; import '../interfaces/ISharedTypes.sol'; /// @title Input Building Library /// @notice Provides functions to build input for swap related actions /// @dev Please note that these functions are very expensive. Ideally, these would be used for off-chain purposes library InputBuilding { /// @notice Takes a list of pairs and returns the input necessary to check the next swap /// @dev Even though this function allows it, the DCAHub will fail if duplicated pairs are used /// @return _tokens A sorted list of all the tokens involved in the swap /// @return _pairsToSwap A sorted list of indexes that represent the pairs involved in the swap function buildGetNextSwapInfoInput(Pair[] calldata _pairs) internal pure returns (address[] memory _tokens, IDCAHub.PairIndexes[] memory _pairsToSwap) { (_tokens, _pairsToSwap, ) = buildSwapInput(_pairs, new IDCAHub.AmountOfToken[](0)); } /// @notice Takes a list of pairs and a list of tokens to borrow and returns the input necessary to execute a swap /// @dev Even though this function allows it, the DCAHub will fail if duplicated pairs are used /// @return _tokens A sorted list of all the tokens involved in the swap /// @return _pairsToSwap A sorted list of indexes that represent the pairs involved in the swap /// @return _borrow A list of amounts to borrow, based on the sorted token list function buildSwapInput(Pair[] calldata _pairs, IDCAHub.AmountOfToken[] memory _toBorrow) internal pure returns ( address[] memory _tokens, IDCAHub.PairIndexes[] memory _pairsToSwap, uint256[] memory _borrow ) { _tokens = _calculateUniqueTokens(_pairs, _toBorrow); _pairsToSwap = _calculatePairIndexes(_pairs, _tokens); _borrow = _calculateTokensToBorrow(_toBorrow, _tokens); } /// @dev Given a list of token pairs and tokens to borrow, returns a list of all the tokens involved, sorted function _calculateUniqueTokens(Pair[] memory _pairs, IDCAHub.AmountOfToken[] memory _toBorrow) private pure returns (address[] memory _tokens) { uint256 _uniqueTokens; address[] memory _tokensPlaceholder = new address[](_pairs.length * 2 + _toBorrow.length); // Load tokens in pairs onto placeholder for (uint256 i; i < _pairs.length; i++) { bool _foundA = false; bool _foundB = false; for (uint256 j; j < _uniqueTokens && !(_foundA && _foundB); j++) { if (!_foundA && _tokensPlaceholder[j] == _pairs[i].tokenA) _foundA = true; if (!_foundB && _tokensPlaceholder[j] == _pairs[i].tokenB) _foundB = true; } if (!_foundA) _tokensPlaceholder[_uniqueTokens++] = _pairs[i].tokenA; if (!_foundB) _tokensPlaceholder[_uniqueTokens++] = _pairs[i].tokenB; } // Load tokens to borrow onto placeholder for (uint256 i; i < _toBorrow.length; i++) { bool _found = false; for (uint256 j; j < _uniqueTokens && !_found; j++) { if (_tokensPlaceholder[j] == _toBorrow[i].token) _found = true; } if (!_found) _tokensPlaceholder[_uniqueTokens++] = _toBorrow[i].token; } // Load sorted into new array _tokens = new address[](_uniqueTokens); for (uint256 i; i < _uniqueTokens; i++) { address _token = _tokensPlaceholder[i]; // Find index where the token should be uint256 _tokenIndex; while (_tokens[_tokenIndex] < _token && _tokens[_tokenIndex] != address(0)) _tokenIndex++; // Move everything one place back for (uint256 j = i; j > _tokenIndex; j--) { _tokens[j] = _tokens[j - 1]; } // Set token on the correct index _tokens[_tokenIndex] = _token; } } /// @dev Given a list of pairs, and a list of sorted tokens, it translates the first list into indexes of the second list. This list of indexes will /// be sorted. For example, if pairs are [{ tokenA, tokenB }, { tokenC, tokenB }] and tokens are: [ tokenA, tokenB, tokenC ], the following is returned /// [ { 0, 1 }, { 1, 1 }, { 1, 2 } ] function _calculatePairIndexes(Pair[] calldata _pairs, address[] memory _tokens) private pure returns (IDCAHub.PairIndexes[] memory _pairIndexes) { _pairIndexes = new IDCAHub.PairIndexes[](_pairs.length); uint256 _count; for (uint8 i; i < _tokens.length; i++) { for (uint8 j = i + 1; j < _tokens.length; j++) { for (uint256 k; k < _pairs.length; k++) { if ( (_tokens[i] == _pairs[k].tokenA && _tokens[j] == _pairs[k].tokenB) || (_tokens[i] == _pairs[k].tokenB && _tokens[j] == _pairs[k].tokenA) ) { _pairIndexes[_count++] = IDCAHubSwapHandler.PairIndexes({indexTokenA: i, indexTokenB: j}); } } } } } /// @dev Given a list of tokens to borrow and a list of sorted tokens, it translated the first list into a list of amounts, sorted by the indexed of /// the seconds list. For example, if `toBorrow` are [{ tokenA, 100 }, { tokenC, 200 }, { tokenB, 500 }] and tokens are [ tokenA, tokenB, tokenC], the /// following is returned [100, 500, 200] function _calculateTokensToBorrow(IDCAHub.AmountOfToken[] memory _toBorrow, address[] memory _tokens) private pure returns (uint256[] memory _borrow) { _borrow = new uint256[](_tokens.length); for (uint256 i; i < _toBorrow.length; i++) { uint256 j; while (_tokens[j] != _toBorrow[i].token) j++; _borrow[j] = _toBorrow[i].amount; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.22; import {IPermit2} from '../interfaces/external/IPermit2.sol'; /** * @title Permit2 Transfers Library * @author Sam Bugs * @notice A small library to call Permit2's transfer from methods */ library Permit2Transfers { /** * @notice Executes a transfer from using Permit2 * @param _permit2 The Permit2 contract * @param _token The token to transfer * @param _amount The amount to transfer * @param _nonce The owner's nonce * @param _deadline The signature's expiration deadline * @param _signature The signature that allows the transfer * @param _recipient The address that will receive the funds */ function takeFromCaller( IPermit2 _permit2, address _token, uint256 _amount, uint256 _nonce, uint256 _deadline, bytes calldata _signature, address _recipient ) internal { _permit2.permitTransferFrom( // The permit message. IPermit2.PermitTransferFrom({permitted: IPermit2.TokenPermissions({token: _token, amount: _amount}), nonce: _nonce, deadline: _deadline}), // The transfer recipient and amount. IPermit2.SignatureTransferDetails({to: _recipient, requestedAmount: _amount}), // The owner of the tokens, which must also be // the signer of the message, otherwise this call // will fail. msg.sender, // The packed signature that was the result of signing // the EIP712 hash of `permit`. _signature ); } /** * @notice Executes a batch transfer from using Permit2 * @param _permit2 The Permit2 contract * @param _tokens The amount of tokens to transfer * @param _nonce The owner's nonce * @param _deadline The signature's expiration deadline * @param _signature The signature that allows the transfer * @param _recipient The address that will receive the funds */ function batchTakeFromCaller( IPermit2 _permit2, IPermit2.TokenPermissions[] calldata _tokens, uint256 _nonce, uint256 _deadline, bytes calldata _signature, address _recipient ) internal { if (_tokens.length > 0) { _permit2.permitTransferFrom( // The permit message. IPermit2.PermitBatchTransferFrom({permitted: _tokens, nonce: _nonce, deadline: _deadline}), // The transfer recipients and amounts. _buildTransferDetails(_tokens, _recipient), // The owner of the tokens, which must also be // the signer of the message, otherwise this call // will fail. msg.sender, // The packed signature that was the result of signing // the EIP712 hash of `permit`. _signature ); } } function _buildTransferDetails(IPermit2.TokenPermissions[] calldata _tokens, address _recipient) private pure returns (IPermit2.SignatureTransferDetails[] memory _details) { _details = new IPermit2.SignatureTransferDetails[](_tokens.length); for (uint256 i; i < _details.length; ++i) { _details[i] = IPermit2.SignatureTransferDetails({to: _recipient, requestedAmount: _tokens[i].amount}); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7; import '@mean-finance/dca-v2-core/contracts/interfaces/IDCAHub.sol'; import '@mean-finance/dca-v2-core/contracts/libraries/TokenSorting.sol'; import '@mean-finance/dca-v2-core/contracts/libraries/Intervals.sol'; import '../interfaces/ISharedTypes.sol'; /** * @title Seconds Until Next Swap Library * @notice Provides functions to calculate how long users have to wait until a pair's next swap is available */ library SecondsUntilNextSwap { /** * @notice Returns how many seconds left until the next swap is available for a specific pair * @dev _tokenA and _tokenB may be passed in either tokenA/tokenB or tokenB/tokenA order * @param _hub The address of the DCA Hub * @param _tokenA One of the pair's tokens * @param _tokenB The other of the pair's tokens * @param _calculatePrivilegedAvailability Some accounts get privileged availability and can execute swaps before others. This flag provides * the possibility to calculate the seconds until next swap for privileged and non-privileged accounts * @return The amount of seconds until next swap. Returns 0 if a swap can already be executed and max(uint256) if there is nothing to swap */ function secondsUntilNextSwap( IDCAHub _hub, address _tokenA, address _tokenB, bool _calculatePrivilegedAvailability ) internal view returns (uint256) { (address __tokenA, address __tokenB) = TokenSorting.sortTokens(_tokenA, _tokenB); bytes1 _activeIntervals = _hub.activeSwapIntervals(__tokenA, __tokenB); bytes1 _mask = 0x01; uint256 _smallerIntervalBlocking; while (_activeIntervals >= _mask && _mask > 0) { if (_activeIntervals & _mask == _mask) { (, uint224 _nextAmountToSwapAToB, uint32 _lastSwappedAt, uint224 _nextAmountToSwapBToA) = _hub.swapData(_tokenA, _tokenB, _mask); uint32 _swapInterval = Intervals.maskToInterval(_mask); uint256 _nextAvailable = ((_lastSwappedAt / _swapInterval) + 1) * _swapInterval; if (!_calculatePrivilegedAvailability) { // If the caller does not have privileges, then they will have to wait a little more to execute swaps _nextAvailable += _swapInterval / 3; } if (_nextAmountToSwapAToB > 0 || _nextAmountToSwapBToA > 0) { if (_nextAvailable <= block.timestamp) { return _smallerIntervalBlocking; } else { return _nextAvailable - block.timestamp; } } else if (_nextAvailable > block.timestamp) { _smallerIntervalBlocking = _smallerIntervalBlocking == 0 ? _nextAvailable - block.timestamp : _smallerIntervalBlocking; } } _mask <<= 1; } return type(uint256).max; } /** * @notice Returns how many seconds left until the next swap is available for a list of pairs * @dev Tokens in pairs may be passed in either tokenA/tokenB or tokenB/tokenA order * @param _hub The address of the DCA Hub * @param _pairs Pairs to check * @return _seconds The amount of seconds until next swap for each of the pairs * @param _calculatePrivilegedAvailability Some accounts get privileged availability and can execute swaps before others. This flag provides * the possibility to calculate the seconds until next swap for privileged and non-privileged accounts */ function secondsUntilNextSwap( IDCAHub _hub, Pair[] calldata _pairs, bool _calculatePrivilegedAvailability ) internal view returns (uint256[] memory _seconds) { _seconds = new uint256[](_pairs.length); for (uint256 i; i < _pairs.length; i++) { _seconds[i] = secondsUntilNextSwap(_hub, _pairs[i].tokenA, _pairs[i].tokenB, _calculatePrivilegedAvailability); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.22; import './SwapAdapter.sol'; import './PayableMulticall.sol'; import {SimulationAdapter} from '@mean-finance/call-simulation/contracts/SimulationAdapter.sol'; import {IPermit2} from '../interfaces/external/IPermit2.sol'; import {Permit2Transfers} from '../libraries/Permit2Transfers.sol'; import './Governable.sol'; /** * @notice This contract will work as base companion for all our contracts. It will extend the capabilities of our companion * contracts so that they can execute multicalls, swaps, revokes and more * @dev All public functions are payable, so that they can be multicalled together with other payable functions when msg.value > 0 */ abstract contract BaseCompanion is SimulationAdapter, Governable, SwapAdapter, PayableMulticall { using Permit2Transfers for IPermit2; using SafeERC20 for IERC20; /** * @notice Returns the address of the Permit2 contract * @dev This value is constant and cannot change * @return The address of the Permit2 contract */ // solhint-disable-next-line var-name-mixedcase IPermit2 public immutable PERMIT2; /// @notice The address of the swapper address public swapper; /// @notice The address of the allowance target address public allowanceTarget; constructor( address _swapper, address _allowanceTarget, address _governor, IPermit2 _permit2 ) SwapAdapter() Governable(_governor) { swapper = _swapper; allowanceTarget = _allowanceTarget; PERMIT2 = _permit2; } receive() external payable {} /** * @notice Sends the specified amount of the given token to the recipient * @param _token The token to transfer * @param _amount The amount to transfer * @param _recipient The recipient of the token balance */ function sendToRecipient( address _token, uint256 _amount, address _recipient ) external payable { _sendToRecipient(_token, _amount, _recipient); } /** * @notice Takes the given amount of tokens from the caller and transfers it to this contract * @param _token The token to take * @param _amount The amount to take */ function takeFromCaller( IERC20 _token, uint256 _amount, address _recipient ) external payable { _token.safeTransferFrom(msg.sender, _recipient, _amount); } /** * @notice Executes a swap against the swapper * @param _allowanceToken The token to set allowance for (can be set to zero address to ignore) * @param _value The value to send to the swapper as part of the swap * @param _swapData The swap data * @param _tokenOut The token that will be bought as part of the swap */ function runSwap( address _allowanceToken, uint256 _value, bytes calldata _swapData, address _tokenOut ) external payable returns (uint256 _amountOut) { if (_allowanceToken != address(0)) { IERC20(_allowanceToken).forceApprove(allowanceTarget, type(uint256).max); } _executeSwap(swapper, _swapData, _value); _amountOut = _tokenOut == PROTOCOL_TOKEN ? address(this).balance : IERC20(_tokenOut).balanceOf(address(this)); } /** * @notice Takes the given amount of tokens from the caller with Permit2 and transfers it to this contract * @param _token The token to take * @param _amount The amount to take * @param _nonce The signed nonce * @param _deadline The signature's deadline * @param _signature The owner's signature * @param _recipient The address that will receive the funds */ function permitTakeFromCaller( address _token, uint256 _amount, uint256 _nonce, uint256 _deadline, bytes calldata _signature, address _recipient ) external payable { PERMIT2.takeFromCaller(_token, _amount, _nonce, _deadline, _signature, _recipient); } /** * @notice Takes the a batch of tokens from the caller with Permit2 and transfers it to this contract * @param _tokens The tokens to take * @param _nonce The signed nonce * @param _deadline The signature's deadline * @param _signature The owner's signature * @param _recipient The address that will receive the funds */ function batchPermitTakeFromCaller( IPermit2.TokenPermissions[] calldata _tokens, uint256 _nonce, uint256 _deadline, bytes calldata _signature, address _recipient ) external payable { PERMIT2.batchTakeFromCaller(_tokens, _nonce, _deadline, _signature, _recipient); } /** * @notice Checks if the contract has any balance of the given token, and if it does, * it sends it to the given recipient * @param _token The token to check * @param _recipient The recipient of the token balance */ function sendBalanceOnContractToRecipient(address _token, address _recipient) external payable { _sendBalanceOnContractToRecipient(_token, _recipient); } /** * @notice Sets a new swapper and allowance target * @param _newSwapper The address of the new swapper * @param _newAllowanceTarget The address of the new allowance target */ function setSwapper(address _newSwapper, address _newAllowanceTarget) external onlyGovernor { swapper = _newSwapper; allowanceTarget = _newAllowanceTarget; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; import './interfaces/IGovernable.sol'; /** * @notice This contract is meant to be used in other contracts. By using this contract, * a specific address will be given a "governor" role, which basically will be able to * control certains aspects of the contract. There are other contracts that do the same, * but this contract forces a new governor to accept the role before it's transferred. * This is a basically a safety measure to prevent losing access to the contract. */ abstract contract Governable is IGovernable { /// @inheritdoc IGovernable address public governor; /// @inheritdoc IGovernable address public pendingGovernor; constructor(address _governor) { if (_governor == address(0)) revert GovernorIsZeroAddress(); governor = _governor; } /// @inheritdoc IGovernable function isGovernor(address _account) public view returns (bool) { return _account == governor; } /// @inheritdoc IGovernable function isPendingGovernor(address _account) public view returns (bool) { return _account == pendingGovernor; } /// @inheritdoc IGovernable function setPendingGovernor(address _pendingGovernor) external onlyGovernor { pendingGovernor = _pendingGovernor; emit PendingGovernorSet(_pendingGovernor); } /// @inheritdoc IGovernable function acceptPendingGovernor() external onlyPendingGovernor { governor = pendingGovernor; pendingGovernor = address(0); emit PendingGovernorAccepted(); } modifier onlyGovernor() { if (!isGovernor(msg.sender)) revert OnlyGovernor(); _; } modifier onlyPendingGovernor() { if (!isPendingGovernor(msg.sender)) revert OnlyPendingGovernor(); _; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; import '@openzeppelin/contracts/utils/Address.sol'; /** * @dev Adding this contract will enable batching calls. This is basically the same as Open Zeppelin's * Multicall contract, but we have made it payable. It supports both payable and non payable * functions. However, if `msg.value` is not zero, then non payable functions cannot be called. * Any contract that uses this Multicall version should be very careful when using msg.value. * For more context, read: https://github.com/Uniswap/v3-periphery/issues/52 */ abstract contract PayableMulticall { /** * @notice Receives and executes a batch of function calls on this contract. * @param _data A list of different function calls to execute * @return _results The result of executing each of those calls */ function multicall(bytes[] calldata _data) external payable returns (bytes[] memory _results) { _results = new bytes[](_data.length); for (uint256 i = 0; i < _data.length; ) { _results[i] = Address.functionDelegateCall(address(this), _data[i]); unchecked { i++; } } return _results; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/utils/Address.sol'; abstract contract SwapAdapter { using SafeERC20 for IERC20; using Address for address; using Address for address payable; /// @notice Describes how the allowance should be revoked for the given spender struct RevokeAction { address spender; IERC20[] tokens; } address public constant PROTOCOL_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /** * @notice Takes the given amount of tokens from the caller * @param _token The token to check * @param _amount The amount to take */ function _takeFromMsgSender(IERC20 _token, uint256 _amount) internal virtual { _token.safeTransferFrom(msg.sender, address(this), _amount); } /** * @notice Executes a swap for the given swapper * @param _swapper The actual swapper * @param _swapData The swap execution data */ function _executeSwap( address _swapper, bytes calldata _swapData, uint256 _value ) internal virtual { _swapper.functionCallWithValue(_swapData, _value); } /** * @notice Transfers the given amount of tokens from the contract to the recipient * @param _token The token to check * @param _amount The amount to send * @param _recipient The recipient */ function _sendToRecipient( address _token, uint256 _amount, address _recipient ) internal virtual { if (_recipient == address(0)) _recipient = msg.sender; if (_token == PROTOCOL_TOKEN) { payable(_recipient).sendValue(_amount); } else { IERC20(_token).safeTransfer(_recipient, _amount); } } /** * @notice Checks if the contract has any balance of the given token, and if it does, * it sends it to the given recipient * @param _token The token to check * @param _recipient The recipient of the token balance */ function _sendBalanceOnContractToRecipient(address _token, address _recipient) internal virtual { uint256 _balance = _token == PROTOCOL_TOKEN ? address(this).balance : IERC20(_token).balanceOf(address(this)); if (_balance > 0) { _sendToRecipient(_token, _balance, _recipient); } } /** * @notice Revokes ERC20 allowances for the given spenders * @dev If exposed, then it should be permissioned * @param _revokeActions The spenders and tokens to revoke */ function _revokeAllowances(RevokeAction[] calldata _revokeActions) internal virtual { for (uint256 i = 0; i < _revokeActions.length; ) { RevokeAction memory _action = _revokeActions[i]; for (uint256 j = 0; j < _action.tokens.length; ) { _action.tokens[j].forceApprove(_action.spender, 0); unchecked { j++; } } unchecked { i++; } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; /** * @title A contract that manages a "governor" role */ interface IGovernable { /// @notice Thrown when trying to set the zero address as governor error GovernorIsZeroAddress(); /// @notice Thrown when trying to execute an action that only the governor an execute error OnlyGovernor(); /// @notice Thrown when trying to execute an action that only the pending governor an execute error OnlyPendingGovernor(); /** * @notice Emitted when a new pending governor is set * @param newPendingGovernor The new pending governor */ event PendingGovernorSet(address newPendingGovernor); /** * @notice Emitted when the pending governor accepts the role and becomes the governor */ event PendingGovernorAccepted(); /** * @notice Returns the address of the governor * @return The address of the governor */ function governor() external view returns (address); /** * @notice Returns the address of the pending governor * @return The address of the pending governor */ function pendingGovernor() external view returns (address); /** * @notice Returns whether the given account is the current governor * @param account The account to check * @return Whether it is the current governor or not */ function isGovernor(address account) external view returns (bool); /** * @notice Returns whether the given account is the pending governor * @param account The account to check * @return Whether it is the pending governor or not */ function isPendingGovernor(address account) external view returns (bool); /** * @notice Sets a new pending governor * @dev Only the current governor can execute this action * @param pendingGovernor The new pending governor */ function setPendingGovernor(address pendingGovernor) external; /** * @notice Sets the pending governor as the governor * @dev Only the pending governor can execute this action */ function acceptPendingGovernor() external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ 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 (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../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; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @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); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.7 <0.9.0; /** * @title The interface for generating a description for a position in a DCA Hub * @notice Contracts that implement this interface must return a base64 JSON with the entire description */ interface IDCAHubPositionDescriptor { /** * @notice Generates a positions's description, both the JSON and the image inside * @param hub The address of the DCA Hub * @param positionId The token/position id * @return description The position's description */ function tokenURI(address hub, uint256 positionId) external view returns (string memory description); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title The interface for an oracle that provides price quotes * @notice These methods allow users to add support for pairs, and then ask for quotes */ interface ITokenPriceOracle { /// @notice Thrown when trying to add support for a pair that cannot be supported error PairCannotBeSupported(address tokenA, address tokenB); /// @notice Thrown when trying to execute a quote with a pair that isn't supported yet error PairNotSupportedYet(address tokenA, address tokenB); /** * @notice Returns whether this oracle can support the given pair of tokens * @dev tokenA and tokenB may be passed in either tokenA/tokenB or tokenB/tokenA order * @param tokenA One of the pair's tokens * @param tokenB The other of the pair's tokens * @return Whether the given pair of tokens can be supported by the oracle */ function canSupportPair(address tokenA, address tokenB) external view returns (bool); /** * @notice Returns whether this oracle is already supporting the given pair of tokens * @dev tokenA and tokenB may be passed in either tokenA/tokenB or tokenB/tokenA order * @param tokenA One of the pair's tokens * @param tokenB The other of the pair's tokens * @return Whether the given pair of tokens is already being supported by the oracle */ function isPairAlreadySupported(address tokenA, address tokenB) external view returns (bool); /** * @notice Returns a quote, based on the given tokens and amount * @dev Will revert if pair isn't supported * @param tokenIn The token that will be provided * @param amountIn The amount that will be provided * @param tokenOut The token we would like to quote * @param data Custom data that the oracle might need to operate * @return amountOut How much `tokenOut` will be returned in exchange for `amountIn` amount of `tokenIn` */ function quote( address tokenIn, uint256 amountIn, address tokenOut, bytes calldata data ) external view returns (uint256 amountOut); /** * @notice Add or reconfigures the support for a given pair. This function will let the oracle take some actions * to configure the pair, in preparation for future quotes. Can be called many times in order to let the oracle * re-configure for a new context * @dev Will revert if pair cannot be supported. tokenA and tokenB may be passed in either tokenA/tokenB or tokenB/tokenA order * @param tokenA One of the pair's tokens * @param tokenB The other of the pair's tokens * @param data Custom data that the oracle might need to operate */ function addOrModifySupportForPair( address tokenA, address tokenB, bytes calldata data ) external; /** * @notice Adds support for a given pair if the oracle didn't support it already. If called for a pair that is already supported, * then nothing will happen. This function will let the oracle take some actions to configure the pair, in preparation * for future quotes * @dev Will revert if pair cannot be supported. tokenA and tokenB may be passed in either tokenA/tokenB or tokenB/tokenA order * @param tokenA One of the pair's tokens * @param tokenB The other of the pair's tokens * @param data Custom data that the oracle might need to operate */ function addSupportForPairIfNeeded( address tokenA, address tokenB, bytes calldata data ) external; }
{ "viaIR": false, "optimizer": { "runs": 9999, "enabled": true }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {}, "remappings": [ "@openzeppelin/contracts/=node_modules/@mean-finance/dca-v2-periphery/node_modules/@openzeppelin/contracts/", "@mean-finance/oracles/=node_modules/@mean-finance/oracles/", "@mean-finance/nft-descriptors/=node_modules/@mean-finance/nft-descriptors/", "@mean-finance/call-simulation/contracts/=node_modules/@mean-finance/call-simulation/src/", "@mean-finance/swappers/=node_modules/@mean-finance/swappers/", "@mean-finance/dca-v2-core/=node_modules/@mean-finance/dca-v2-core/", "@mean-finance/permit2-adapter/=node_modules/@mean-finance/permit2-adapter/src/", "@mean-finance/transformers/=node_modules/@mean-finance/transformers/solidity/contracts/transformers/", "@mean-finance/dca-v2-periphery/=node_modules/@mean-finance/dca-v2-periphery/", "@mean-finance/uniswap-v3-oracle/=node_modules/@mean-finance/uniswap-v3-oracle/", "@call-simulation/=node_modules/@mean-finance/call-simulation/src/", "@chainlink/=node_modules/@chainlink/", "@api3/=node_modules/@api3/", "@uniswap/=node_modules/@uniswap/", "keep3r-v2/=node_modules/keep3r-v2/", "base64-sol/=node_modules/base64-sol/", "@sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry/", "forge-std/=lib/forge-std/src/", "@rari-capital/solmate/=lib/solmate/", "ds-test/=lib/solmate/lib/ds-test/src/", "solmate/=lib/solmate/src/", "sphinx/=lib/sphinx/packages/contracts/contracts/forge-std/src/" ] }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_swapper","type":"address"},{"internalType":"address","name":"_allowanceTarget","type":"address"},{"internalType":"address","name":"_governor","type":"address"},{"internalType":"contract IPermit2","name":"_permit2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"GovernorIsZeroAddress","type":"error"},{"inputs":[],"name":"InvalidMask","type":"error"},{"inputs":[],"name":"OnlyGovernor","type":"error"},{"inputs":[],"name":"OnlyPendingGovernor","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"},{"internalType":"uint256","name":"gasSpent","type":"uint256"}],"internalType":"struct ISimulationAdapter.SimulationResult","name":"result","type":"tuple"}],"name":"SimulatedCall","type":"error"},{"inputs":[],"name":"UnauthorizedCaller","type":"error"},{"anonymous":false,"inputs":[],"name":"PendingGovernorAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPendingGovernor","type":"address"}],"name":"PendingGovernorSet","type":"event"},{"inputs":[],"name":"PERMIT2","outputs":[{"internalType":"contract IPermit2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROTOCOL_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptPendingGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowanceTarget","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPermit2.TokenPermissions[]","name":"_tokens","type":"tuple[]"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"batchPermitTakeFromCaller","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_amountOfSwaps","type":"uint32"},{"internalType":"uint32","name":"_swapInterval","type":"uint32"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"enum IDCAPermissionManager.Permission[]","name":"permissions","type":"uint8[]"}],"internalType":"struct IDCAPermissionManager.PermissionSet[]","name":"_permissions","type":"tuple[]"},{"internalType":"bytes","name":"_miscellaneous","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"_positionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_amountOfSwaps","type":"uint32"},{"internalType":"uint32","name":"_swapInterval","type":"uint32"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"enum IDCAPermissionManager.Permission[]","name":"permissions","type":"uint8[]"}],"internalType":"struct IDCAPermissionManager.PermissionSet[]","name":"_permissions","type":"tuple[]"},{"internalType":"bytes","name":"_miscellaneous","type":"bytes"}],"name":"depositWithBalanceOnContract","outputs":[{"internalType":"uint256","name":"_positionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct Pair[]","name":"_pairs","type":"tuple[]"},{"internalType":"bool","name":"_calculatePrivilegedAvailability","type":"bool"},{"internalType":"bytes","name":"_oracleData","type":"bytes"}],"name":"getNextSwapInfo","outputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"toProvide","type":"uint256"},{"internalType":"uint256","name":"platformFee","type":"uint256"}],"internalType":"struct IDCAHubSwapHandler.TokenInSwap[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"totalAmountToSwapTokenA","type":"uint256"},{"internalType":"uint256","name":"totalAmountToSwapTokenB","type":"uint256"},{"internalType":"uint256","name":"ratioAToB","type":"uint256"},{"internalType":"uint256","name":"ratioBToA","type":"uint256"},{"internalType":"bytes1","name":"intervalsInSwap","type":"bytes1"}],"internalType":"struct IDCAHubSwapHandler.PairInSwap[]","name":"pairs","type":"tuple[]"}],"internalType":"struct IDCAHubSwapHandler.SwapInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"uint256","name":"_positionId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_newSwaps","type":"uint32"}],"name":"increasePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"uint256","name":"_positionId","type":"uint256"},{"internalType":"uint32","name":"_newSwaps","type":"uint32"}],"name":"increasePositionWithBalanceOnContract","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isPendingGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILegacyDCAHub","name":"_hub","type":"address"},{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct Pair[]","name":"_pairs","type":"tuple[]"}],"name":"legacyGetNextSwapInfo","outputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"toProvide","type":"uint256"},{"internalType":"uint256","name":"platformFee","type":"uint256"}],"internalType":"struct ILegacyDCAHub.TokenInSwap[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"ratioAToB","type":"uint256"},{"internalType":"uint256","name":"ratioBToA","type":"uint256"},{"internalType":"bytes1","name":"intervalsInSwap","type":"bytes1"}],"internalType":"struct ILegacyDCAHub.PairInSwap[]","name":"pairs","type":"tuple[]"}],"internalType":"struct ILegacyDCAHub.SwapInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IDCAPermissionManager","name":"_permissionManager","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"enum IDCAPermissionManager.Permission[]","name":"permissions","type":"uint8[]"}],"internalType":"struct IDCAPermissionManager.PermissionSet[]","name":"permissionSets","type":"tuple[]"}],"internalType":"struct IDCAPermissionManager.PositionPermissions[]","name":"_permissions","type":"tuple[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"multiPermissionPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"_results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"pendingGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IDCAPermissionManager","name":"_permissionManager","type":"address"},{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"enum IDCAPermissionManager.Permission[]","name":"permissions","type":"uint8[]"}],"internalType":"struct IDCAPermissionManager.PermissionSet[]","name":"_permissions","type":"tuple[]"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permissionPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"permitTakeFromCaller","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"uint256","name":"_positionId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_newSwaps","type":"uint32"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"reducePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_allowanceToken","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"runSwap","outputs":[{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct Pair[]","name":"_pairs","type":"tuple[]"},{"internalType":"bool","name":"_calculatePrivilegedAvailability","type":"bool"}],"name":"secondsUntilNextSwap","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"sendBalanceOnContractToRecipient","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"sendToRecipient","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingGovernor","type":"address"}],"name":"setPendingGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSwapper","type":"address"},{"internalType":"address","name":"_newAllowanceTarget","type":"address"}],"name":"setSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_calls","type":"bytes[]"}],"name":"simulate","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"},{"internalType":"uint256","name":"gasSpent","type":"uint256"}],"internalType":"struct ISimulationAdapter.SimulationResult[]","name":"_results","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_call","type":"bytes"}],"name":"simulateAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"takeFromCaller","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"uint256","name":"_positionId","type":"uint256"},{"internalType":"address","name":"_recipientUnswapped","type":"address"},{"internalType":"address","name":"_recipientSwapped","type":"address"}],"name":"terminate","outputs":[{"internalType":"uint256","name":"_unswapped","type":"uint256"},{"internalType":"uint256","name":"_swapped","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"internalType":"uint256","name":"_positionId","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"withdrawSwapped","outputs":[{"internalType":"uint256","name":"_swapped","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDCAHub","name":"_hub","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"positionIds","type":"uint256[]"}],"internalType":"struct IDCAHubPositionHandler.PositionSet[]","name":"_positions","type":"tuple[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"withdrawSwappedMany","outputs":[{"internalType":"uint256[]","name":"_withdrawn","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200553d3803806200553d8339810160408190526200003491620000ca565b83838383816001600160a01b038116620000615760405163e6250e3360e01b815260040160405180910390fd5b600080546001600160a01b03199081166001600160a01b03938416179091556002805482169683169690961790955560038054909516938116939093179093555016608052506200013292505050565b6001600160a01b0381168114620000c757600080fd5b50565b60008060008060808587031215620000e157600080fd5b8451620000ee81620000b1565b60208601519094506200010181620000b1565b60408601519093506200011481620000b1565b60608601519092506200012781620000b1565b939692955090935050565b6080516153e16200015c6000396000818161048201528181610fc8015261140201526153e16000f3fe60806040526004361061021d5760003560e01c806362b850c71161011d578063bcbef206116100b0578063e3056a341161007f578063effca70511610064578063effca705146105e1578063f235757f14610601578063fa0c95551461062157600080fd5b8063e3056a3414610592578063e43581b8146105b257600080fd5b8063bcbef2061461052a578063d9a673ef1461053d578063db8266de14610550578063df08aed51461056357600080fd5b8063910cab11116100ec578063910cab11146104b7578063a669a7f6146104d7578063ac9650d8146104ea578063bb2871a51461050a57600080fd5b806362b850c71461044a57806362dd9af31461045d5780636afdd8501461047057806389352328146104a457600080fd5b806335ac2a50116101b057806340c5710c1161017f5780635684c275116101645780635684c275146103cd578063585cc6a5146103fa5780635f963dcf1461042257600080fd5b806340c5710c1461038d578063484b3577146103a057600080fd5b806335ac2a501461032757806337b0c09d146103475780633a79d6741461035a5780633ed242b41461036d57600080fd5b80631f66925c116101ec5780631f66925c146102c05780631f8b479d146102e15780632b3297f9146102f4578063340b532f1461031457600080fd5b806301ffc9a71461022957806305ce20d61461025e5780630c340a241461027357806313f6986d146102ab57600080fd5b3661022457005b600080fd5b34801561023557600080fd5b50610249610244366004613395565b610634565b60405190151581526020015b60405180910390f35b61027161026c36600461340e565b6106cd565b005b34801561027f57600080fd5b50600054610293906001600160a01b031681565b6040516001600160a01b039091168152602001610255565b3480156102b757600080fd5b50610271610801565b6102d36102ce366004613463565b6108ad565b604051908152602001610255565b6102716102ef366004613502565b610955565b34801561030057600080fd5b50600254610293906001600160a01b031681565b61027161032236600461358e565b6109a6565b61033a6103353660046135c7565b6109b4565b6040516102559190613624565b610271610355366004613463565b610b03565b610271610368366004613463565b610b1d565b61038061037b366004613668565b610b28565b604051610255919061372f565b61027161039b3660046137b1565b610c00565b3480156103ac57600080fd5b506103c06103bb36600461387d565b610d83565b6040516102559190613914565b3480156103d957600080fd5b506103ed6103e8366004613a45565b610e48565b6040516102559190613a9a565b34801561040657600080fd5b5061029373eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b610435610430366004613ba8565b610f06565b60408051928352602083019190915201610255565b610271610458366004613bf0565b610fbb565b61027161046b366004613c87565b610ffd565b34801561047c57600080fd5b506102937f000000000000000000000000000000000000000000000000000000000000000081565b6102d36104b2366004613d0a565b611087565b3480156104c357600080fd5b50600354610293906001600160a01b031681565b6102d36104e5366004613deb565b611132565b6104fd6104f8366004613668565b61122d565b6040516102559190613e5f565b34801561051657600080fd5b5061033a610525366004613ed4565b611310565b610271610538366004613f31565b611326565b61027161054b366004613f67565b6113f5565b61027161055e366004613fde565b61142e565b34801561056f57600080fd5b5061024961057e36600461402f565b6001546001600160a01b0391821691161490565b34801561059e57600080fd5b50600154610293906001600160a01b031681565b3480156105be57600080fd5b506102496105cd36600461402f565b6000546001600160a01b0391821691161490565b3480156105ed57600080fd5b506102716105fc36600461358e565b61149e565b34801561060d57600080fd5b5061027161061c36600461402f565b611528565b6102d361062f36600461404c565b6115d8565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f3ed242b40000000000000000000000000000000000000000000000000000000014806106c757507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b838360006106dc83838361171f565b6040517f5b6fd01d000000000000000000000000000000000000000000000000000000008152600481018790526000906001600160a01b03891690635b6fd01d9060240161010060405180830381865afa15801561073e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107629190614261565b519050610770818988611827565b6040517fded700a6000000000000000000000000000000000000000000000000000000008152600481018890526024810187905263ffffffff861660448201526001600160a01b0389169063ded700a6906064015b600060405180830381600087803b1580156107df57600080fd5b505af11580156107f3573d6000803e3d6000fd5b505050505050505050505050565b6001546001600160a01b03163314610845576040517f9ba0305d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018054600080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b0384161782559091169091556040517fdc57ca23c46d823853915ed5a090ca0ee9db5eb6a46f5c58e1c9158de861fd769190a1565b6000838360026108be83838361171f565b6040517f17621890000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301528816906317621890906044016020604051808303816000875af1158015610926573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a919061431d565b979650505050505050565b6040517f4faa38830000000000000000000000000000000000000000000000000000000081526001600160a01b03891690634faa3883906107c5908a908a908a908a908a908a908a906004016144da565b6109b082826118da565b5050565b606060005b83811015610a695760008585838181106109d5576109d561451b565b90506020028101906109e7919061454a565b6109f5906020810190614588565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394505050505b8151811015610a5f57610a5788838381518110610a4857610a4861451b565b6020026020010151600261171f565b600101610a29565b50506001016109b9565b506040517f480b37960000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063480b379690610ab3908790879087906004016145f0565b6000604051808303816000875af1158015610ad2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610afa9190810190614708565b95945050505050565b610b186001600160a01b03841633838561199b565b505050565b610b18838383611a17565b60608167ffffffffffffffff811115610b4357610b4361413a565b604051908082528060200260200182016040528015610b9a57816020015b610b87604051806060016040528060001515815260200160608152602001600081525090565b815260200190600190039081610b615790505b50905060005b82811015610bf957610bd4848483818110610bbd57610bbd61451b565b9050602002810190610bcf9190614793565b611a7f565b828281518110610be657610be661451b565b6020908102919091010152600101610ba0565b5092915050565b82826000610c0f83838361171f565b6040517f5b6fd01d000000000000000000000000000000000000000000000000000000008152600481018690526000906001600160a01b03881690635b6fd01d9060240161010060405180830381865afa158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614261565b516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610cf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1d919061431d565b9050610d2a828983611827565b6040517fded700a6000000000000000000000000000000000000000000000000000000008152600481018890526024810182905263ffffffff871660448201526001600160a01b0389169063ded700a6906064016107c5565b6040805180820190915260608082526020820152600080610da48888611bff565b6040517f4997cdc300000000000000000000000000000000000000000000000000000000815291935091506001600160a01b038a1690634997cdc390610df690859085908b908b908b906004016148ab565b600060405180830381865afa158015610e13573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e3b91908101906149db565b9998505050505050505050565b6040805180820190915260608082526020820152600080610e698585611bff565b6040517fd2d95b2d00000000000000000000000000000000000000000000000000000000815291935091506001600160a01b0387169063d2d95b2d90610eb59085908590600401614b46565b600060405180830381865afa158015610ed2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610efa9190810190614b6b565b925050505b9392505050565b60008085856003610f1883838361171f565b6040517f72ada4c5000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b03888116602483015287811660448301528a16906372ada4c59060640160408051808303816000875af1158015610f87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fab9190614caf565b909a909950975050505050505050565b610ff46001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001688888888888888611c60565b50505050505050565b6040517f3dff05870000000000000000000000000000000000000000000000000000000081526001600160a01b03881690633dff05879061104c90899089908990899089908990600401614cd3565b600060405180830381600087803b15801561106657600080fd5b505af115801561107a573d6000803e3d6000fd5b5050505050505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009081906001600160a01b038c16906370a0823190602401602060405180830381865afa1580156110e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110d919061431d565b90506111228c8c8c848d8d8d8d8d8d8d6115d8565b9c9b505050505050505050505050565b60006001600160a01b0386161561115f5760035461115f906001600160a01b038881169116600019611d1a565b600254611177906001600160a01b0316858588611dd8565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611221576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156111f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121c919061431d565b611223565b475b9695505050505050565b60608167ffffffffffffffff8111156112485761124861413a565b60405190808252806020026020018201604052801561127b57816020015b60608152602001906001900390816112665790505b50905060005b82811015610bf9576112eb3085858481811061129f5761129f61451b565b90506020028101906112b19190614793565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e2a92505050565b8282815181106112fd576112fd61451b565b6020908102919091010152600101611281565b6060610afa85858585611e97565b949350505050565b60005a9050600080306001600160a01b03168585604051611348929190614d90565b600060405180830381855af49150503d8060008114611383576040519150601f19603f3d011682016040523d82523d6000602084013e611388565b606091505b509150915060005a61139a9085614dcf565b905060405180606001604052808415158152602001838152602001828152506040517f493703af0000000000000000000000000000000000000000000000000000000081526004016113ec9190614de2565b60405180910390fd5b610ff46001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001688888888888888611f73565b8484600161143d83838361171f565b6040517ff1accf39000000000000000000000000000000000000000000000000000000008152600481018890526024810187905263ffffffff861660448201526001600160a01b03858116606483015289169063f1accf39906084016107c5565b6000546001600160a01b031633146114e2576040517fe0a8b92000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280546001600160a01b039384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560038054929093169116179055565b6000546001600160a01b0316331461156c576040517fe0a8b92000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f56bddfa0cee9697cebddf9acd7f23dc6583663b05e007b877056d05017994def9060200160405180910390a150565b60006115e58b8d8b611827565b81611685576040517f6b29e1bd0000000000000000000000000000000000000000000000000000000081526001600160a01b038d1690636b29e1bd9061163d908e908e908e908e908e908e908e908e90600401614df5565b6020604051808303816000875af115801561165c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611680919061431d565b611122565b6040517fb2b513c10000000000000000000000000000000000000000000000000000000081526001600160a01b038d169063b2b513c1906116dc908e908e908e908e908e908e908e908e908e908e90600401614e54565b6020604051808303816000875af11580156116fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611122919061431d565b826001600160a01b031663cc7a20496040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117819190614ecb565b6001600160a01b031663823abfd98333846040518463ffffffff1660e01b81526004016117b093929190614ee8565b602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f19190614f0b565b610b18576040517f5c427cd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b4919061431d565b9050818110156118d4576118d46001600160a01b03851684600019611d1a565b50505050565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611986576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611981919061431d565b611988565b475b90508015610b1857610b18838284611a17565b6040516001600160a01b0384811660248301528381166044830152606482018390526118d49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611ffc565b6001600160a01b038116611a285750335b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6b57610b186001600160a01b03821683612078565b610b186001600160a01b0384168284612141565b611aa5604051806060016040528060001515815260200160608152602001600081525090565b600080306001600160a01b031663bcbef20660e01b8686604051602401611acd929190614f28565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611b389190614f3c565b600060405180830381855af49150503d8060008114611b73576040519150601f19603f3d011682016040523d82523d6000602084013e611b78565b606091505b50915091508115611be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5754463f2053686f756c642068617665206661696c656421000000000000000060448201526064016113ec565b60048101905080806020019051810190610afa9190614f4e565b606080611c5484846000604051908082528060200260200182016040528015611c4e57816020015b6040805180820190915260008082526020820152815260200190600190039081611c275790505b50612172565b50909590945092505050565b8515611d1057876001600160a01b031663edd9444b60405180606001604052808a8a808060200260200160405190810160405280939291908181526020016000905b82821015611cce57611cbf60408302860136819003810190615024565b81526020019060010190611ca2565b5050505050815260200188815260200187815250611ced8a8a866121f7565b3387876040518663ffffffff1660e01b81526004016107c59594939291906150ac565b5050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611d9984826122cc565b6118d4576040516001600160a01b03848116602483015260006044830152611dce91869182169063095ea7b3906064016119d0565b6118d48482611ffc565b611e2383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b0387169190508361236f565b5050505050565b6060600080846001600160a01b031684604051611e479190614f3c565b600060405180830381855af49150503d8060008114611e82576040519150601f19603f3d011682016040523d82523d6000602084013e611e87565b606091505b5091509150610afa858383612417565b60608267ffffffffffffffff811115611eb257611eb261413a565b604051908082528060200260200182016040528015611edb578160200160208202803683370190505b50905060005b83811015611f6a57611f4586868684818110611eff57611eff61451b565b611f15926020604090920201908101915061402f565b878785818110611f2757611f2761451b565b9050604002016020016020810190611f3f919061402f565b8661248c565b828281518110611f5757611f5761451b565b6020908102919091010152600101611ee1565b50949350505050565b6040805160a0810182526001600160a01b0389811660608301908152608083018a9052825260208083018990528284018890528351808501855285831681529081018a905292517f30f28b7a000000000000000000000000000000000000000000000000000000008152908b16926330f28b7a926107c592909190339089908990600401615166565b60006120116001600160a01b03841683612803565b905080516000141580156120365750808060200190518101906120349190614f0b565b155b15610b18576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016113ec565b804710156120b4576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016113ec565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612101576040519150601f19603f3d011682016040523d82523d6000602084013e612106565b606091505b5050905080610b18576040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03838116602483015260448201839052610b1891859182169063a9059cbb906064016119d0565b60608060606121d38686808060200260200160405190810160405280939291908181526020016000905b828210156121c8576121b9604083028601368190038101906151df565b8152602001906001019061219c565b505050505085612811565b92506121e0868685612ccd565b91506121ec8484612f5e565b905093509350939050565b60608267ffffffffffffffff8111156122125761221261413a565b60405190808252806020026020018201604052801561225757816020015b60408051808201909152600080825260208201528152602001906001900390816122305790505b50905060005b81518110156122c4576040518060400160405280846001600160a01b031681526020018686848181106122925761229261451b565b905060400201602001358152508282815181106122b1576122b161451b565b602090810291909101015260010161225d565b509392505050565b6000806000846001600160a01b0316846040516122e99190614f3c565b6000604051808303816000865af19150503d8060008114612326576040519150601f19603f3d011682016040523d82523d6000602084013e61232b565b606091505b50915091508180156123555750805115806123555750808060200190518101906123559190614f0b565b8015610afa5750505050506001600160a01b03163b151590565b6060814710156123ad576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016113ec565b600080856001600160a01b031684866040516123c99190614f3c565b60006040518083038185875af1925050503d8060008114612406576040519150601f19603f3d011682016040523d82523d6000602084013e61240b565b606091505b5091509150610efa8683835b60608261242c576124278261305a565b610eff565b815115801561244357506001600160a01b0384163b155b15612485576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016113ec565b5080610eff565b600080600061249b868661309f565b6040517f582cf84b0000000000000000000000000000000000000000000000000000000081526001600160a01b038084166004830152808316602483015292945090925060009189169063582cf84b90604401602060405180830381865afa15801561250b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252f9190615220565b90507f010000000000000000000000000000000000000000000000000000000000000060005b7fff00000000000000000000000000000000000000000000000000000000000000808316908416108015906125ab57507fff00000000000000000000000000000000000000000000000000000000000000821615155b156127f257817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168284167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036127c4576040517f808ba8e00000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015289811660248301527fff000000000000000000000000000000000000000000000000000000000000008416604483015260009182918291908e169063808ba8e090606401608060405180830381865afa158015612694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b89190615267565b9350935093505060006126ca866130d0565b90506000816126d981866152bf565b6126e4906001615309565b6126ee9190615326565b63ffffffff1690508b612719576127066003836152bf565b6127169063ffffffff168261534e565b90505b6000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16118061276457506000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16115b1561279d5742811161278257859a505050505050505050505061131e565b61278c4282614dcf565b9a505050505050505050505061131e565b428111156127be5785156127b157856127bb565b6127bb4282614dcf565b95505b50505050505b6001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901b9150612555565b506000199998505050505050505050565b6060610eff8383600061236f565b60606000808351855160026128269190615361565b612830919061534e565b67ffffffffffffffff8111156128485761284861413a565b604051908082528060200260200182016040528015612871578160200160208202803683370190505b50905060005b8551811015612a405760008060005b858110801561289c575082801561289a5750815b155b1561297157821580156128f657508884815181106128bc576128bc61451b565b6020026020010151600001516001600160a01b03168582815181106128e3576128e361451b565b60200260200101516001600160a01b0316145b1561290057600192505b81158015612955575088848151811061291b5761291b61451b565b6020026020010151602001516001600160a01b03168582815181106129425761294261451b565b60200260200101516001600160a01b0316145b1561295f57600191505b8061296981615378565b915050612886565b50816129d4578783815181106129895761298961451b565b6020026020010151600001518486806129a190615378565b9750815181106129b3576129b361451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b80612a36578783815181106129eb576129eb61451b565b602002602001015160200151848680612a0390615378565b975081518110612a1557612a1561451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101612877565b5060005b8451811015612b35576000805b8481108015612a5e575081155b15612ac957868381518110612a7557612a7561451b565b6020026020010151600001516001600160a01b0316848281518110612a9c57612a9c61451b565b60200260200101516001600160a01b031603612ab757600191505b80612ac181615378565b915050612a51565b5080612b2c57858281518110612ae157612ae161451b565b602002602001015160000151838580612af990615378565b965081518110612b0b57612b0b61451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b50600101612a44565b508167ffffffffffffffff811115612b4f57612b4f61413a565b604051908082528060200260200182016040528015612b78578160200160208202803683370190505b50925060005b82811015612cc4576000828281518110612b9a57612b9a61451b565b6020026020010151905060005b816001600160a01b0316868281518110612bc357612bc361451b565b60200260200101516001600160a01b0316108015612c0d575060006001600160a01b0316868281518110612bf957612bf961451b565b60200260200101516001600160a01b031614155b15612c245780612c1c81615378565b915050612ba7565b825b81811115612c8e5786612c3a600183614dcf565b81518110612c4a57612c4a61451b565b6020026020010151878281518110612c6457612c6461451b565b6001600160a01b039092166020928302919091019091015280612c8681615392565b915050612c26565b5081868281518110612ca257612ca261451b565b6001600160a01b03909216602092830291909101909101525050600101612b7e565b50505092915050565b60608267ffffffffffffffff811115612ce857612ce861413a565b604051908082528060200260200182016040528015612d2d57816020015b6040805180820190915260008082526020820152815260200190600190039081612d065790505b5090506000805b83518160ff161015612f55576000612d4d8260016153a9565b90505b84518160ff161015612f425760005b86811015612f2f57878782818110612d7957612d7961451b565b612d8f926020604090920201908101915061402f565b6001600160a01b0316868460ff1681518110612dad57612dad61451b565b60200260200101516001600160a01b0316148015612e215750878782818110612dd857612dd861451b565b9050604002016020016020810190612df0919061402f565b6001600160a01b0316868360ff1681518110612e0e57612e0e61451b565b60200260200101516001600160a01b0316145b80612ee15750878782818110612e3957612e3961451b565b9050604002016020016020810190612e51919061402f565b6001600160a01b0316868460ff1681518110612e6f57612e6f61451b565b60200260200101516001600160a01b0316148015612ee15750878782818110612e9a57612e9a61451b565b612eb0926020604090920201908101915061402f565b6001600160a01b0316868360ff1681518110612ece57612ece61451b565b60200260200101516001600160a01b0316145b15612f27576040805180820190915260ff8085168252831660208201528585612f0981615378565b965081518110612f1b57612f1b61451b565b60200260200101819052505b600101612d5f565b5080612f3a816153c2565b915050612d50565b5080612f4d816153c2565b915050612d34565b50509392505050565b6060815167ffffffffffffffff811115612f7a57612f7a61413a565b604051908082528060200260200182016040528015612fa3578160200160208202803683370190505b50905060005b8351811015610bf95760005b848281518110612fc757612fc761451b565b6020026020010151600001516001600160a01b0316848281518110612fee57612fee61451b565b60200260200101516001600160a01b031614613016578061300e81615378565b915050612fb5565b8482815181106130285761302861451b565b6020026020010151602001518382815181106130465761304661451b565b602090810291909101015250600101612fa9565b80511561306a5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600080826001600160a01b0316846001600160a01b0316106130c25782846130c5565b83835b909590945092505050565b60007fff0000000000000000000000000000000000000000000000000000000000000082167f0100000000000000000000000000000000000000000000000000000000000000036131235750603c919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f020000000000000000000000000000000000000000000000000000000000000003613175575061012c919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f0400000000000000000000000000000000000000000000000000000000000000036131c75750610384919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f0800000000000000000000000000000000000000000000000000000000000000036132195750610708919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f10000000000000000000000000000000000000000000000000000000000000000361326b5750610e10919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f2000000000000000000000000000000000000000000000000000000000000000036132bd5750613840919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f400000000000000000000000000000000000000000000000000000000000000003613310575062015180919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f800000000000000000000000000000000000000000000000000000000000000003613363575062093a80919050565b6040517fbf3cad0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156133a757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eff57600080fd5b6001600160a01b038116811461309c57600080fd5b63ffffffff8116811461309c57600080fd5b8035613409816133ec565b919050565b6000806000806080858703121561342457600080fd5b843561342f816133d7565b93506020850135925060408501359150606085013561344d816133ec565b939692955090935050565b8035613409816133d7565b60008060006060848603121561347857600080fd5b8335613483816133d7565b925060208401359150604084013561349a816133d7565b809150509250925092565b60008083601f8401126134b757600080fd5b50813567ffffffffffffffff8111156134cf57600080fd5b6020830191508360208260051b85010111156134ea57600080fd5b9250929050565b803560ff8116811461340957600080fd5b60008060008060008060008060e0898b03121561351e57600080fd5b8835613529816133d7565b9750602089013567ffffffffffffffff81111561354557600080fd5b6135518b828c016134a5565b909850965050604089013594506060890135935061357160808a016134f1565b925060a0890135915060c089013590509295985092959890939650565b600080604083850312156135a157600080fd5b82356135ac816133d7565b915060208301356135bc816133d7565b809150509250929050565b600080600080606085870312156135dd57600080fd5b84356135e8816133d7565b9350602085013567ffffffffffffffff81111561360457600080fd5b613610878288016134a5565b909450925050604085013561344d816133d7565b6020808252825182820181905260009190848201906040850190845b8181101561365c57835183529284019291840191600101613640565b50909695505050505050565b6000806020838503121561367b57600080fd5b823567ffffffffffffffff81111561369257600080fd5b61369e858286016134a5565b90969095509350505050565b60005b838110156136c55781810151838201526020016136ad565b50506000910152565b600081518084526136e68160208601602086016136aa565b601f01601f19169290920160200192915050565b805115158252600060208201516060602085015261371b60608501826136ce565b604093840151949093019390935250919050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156137a4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526137928583516136fa565b94509285019290850190600101613758565b5092979650505050505050565b6000806000606084860312156137c657600080fd5b83356137d1816133d7565b925060208401359150604084013561349a816133ec565b60008083601f8401126137fa57600080fd5b50813567ffffffffffffffff81111561381257600080fd5b6020830191508360208260061b85010111156134ea57600080fd5b801515811461309c57600080fd5b60008083601f84011261384d57600080fd5b50813567ffffffffffffffff81111561386557600080fd5b6020830191508360208285010111156134ea57600080fd5b6000806000806000806080878903121561389657600080fd5b86356138a1816133d7565b9550602087013567ffffffffffffffff808211156138be57600080fd5b6138ca8a838b016137e8565b9097509550604089013591506138df8261382d565b909350606088013590808211156138f557600080fd5b5061390289828a0161383b565b979a9699509497509295939492505050565b60006020808352606080840185516040808588015282825180855260809450608089019150868401935060005b8181101561398e5761397e8386516001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b9387019391850191600101613941565b505088860151888203601f190160408a0152805180835290870193506000918701905b80831015613a3757845180516001600160a01b03908116845289820151168984015284810151858401528781015188840152868101518784015260a0808201519084015260c0908101517fff000000000000000000000000000000000000000000000000000000000000001690830152938701936001929092019160e0909101906139b1565b509998505050505050505050565b600080600060408486031215613a5a57600080fd5b8335613a65816133d7565b9250602084013567ffffffffffffffff811115613a8157600080fd5b613a8d868287016137e8565b9497909650939450505050565b60006020808352606080840185516040808588015282825180855260809450608089019150868401935060005b81811015613b1457613b048386516001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b9387019391850191600101613ac7565b505088860151888203601f190160408a0152805180835290870193506000918701905b80831015613a3757845180516001600160a01b039081168452898201511689840152848101518584015287810151888401528601517fff000000000000000000000000000000000000000000000000000000000000001686830152938701936001929092019160a090910190613b37565b60008060008060808587031215613bbe57600080fd5b8435613bc9816133d7565b9350602085013592506040850135613be0816133d7565b9150606085013561344d816133d7565b600080600080600080600060a0888a031215613c0b57600080fd5b873567ffffffffffffffff80821115613c2357600080fd5b613c2f8b838c016137e8565b909950975060208a0135965060408a0135955060608a0135915080821115613c5657600080fd5b50613c638a828b0161383b565b9094509250506080880135613c77816133d7565b8091505092959891949750929550565b600080600080600080600060c0888a031215613ca257600080fd5b8735613cad816133d7565b9650602088013567ffffffffffffffff811115613cc957600080fd5b613cd58a828b016134a5565b90975095505060408801359350613cee606089016134f1565b92506080880135915060a0880135905092959891949750929550565b6000806000806000806000806000806101008b8d031215613d2a57600080fd5b8a35613d35816133d7565b995060208b0135613d45816133d7565b985060408b0135613d55816133d7565b975060608b0135613d65816133ec565b965060808b0135613d75816133ec565b9550613d8360a08c01613458565b945060c08b013567ffffffffffffffff80821115613da057600080fd5b613dac8e838f016134a5565b909650945060e08d0135915080821115613dc557600080fd5b50613dd28d828e0161383b565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215613e0357600080fd5b8535613e0e816133d7565b945060208601359350604086013567ffffffffffffffff811115613e3157600080fd5b613e3d8882890161383b565b9094509250506060860135613e51816133d7565b809150509295509295909350565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156137a4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613ec28583516136ce565b94509285019290850190600101613e88565b60008060008060608587031215613eea57600080fd5b8435613ef5816133d7565b9350602085013567ffffffffffffffff811115613f1157600080fd5b613f1d878288016137e8565b909450925050604085013561344d8161382d565b60008060208385031215613f4457600080fd5b823567ffffffffffffffff811115613f5b57600080fd5b61369e8582860161383b565b600080600080600080600060c0888a031215613f8257600080fd5b8735613f8d816133d7565b9650602088013595506040880135945060608801359350608088013567ffffffffffffffff811115613fbe57600080fd5b613fca8a828b0161383b565b90945092505060a0880135613c77816133d7565b600080600080600060a08688031215613ff657600080fd5b8535614001816133d7565b94506020860135935060408601359250606086013561401f816133ec565b91506080860135613e51816133d7565b60006020828403121561404157600080fd5b8135610eff816133d7565b60008060008060008060008060008060006101208c8e03121561406e57600080fd5b6140788c356133d7565b8b359a5061408960208d01356133d7565b60208c0135995061409c60408d01613458565b985060608c013597506140b160808d016133fe565b96506140bf60a08d016133fe565b95506140cd60c08d01613458565b945067ffffffffffffffff8060e08e013511156140e957600080fd5b6140f98e60e08f01358f016134a5565b90955093506101008d013581101561411057600080fd5b506141228d6101008e01358e0161383b565b81935080925050509295989b509295989b9093969950565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561418c5761418c61413a565b60405290565b60405160e0810167ffffffffffffffff8111828210171561418c5761418c61413a565b60405160a0810167ffffffffffffffff8111828210171561418c5761418c61413a565b6040516060810167ffffffffffffffff8111828210171561418c5761418c61413a565b604051601f8201601f1916810167ffffffffffffffff811182821017156142245761422461413a565b604052919050565b8051613409816133d7565b8051613409816133ec565b80516effffffffffffffffffffffffffffff8116811461340957600080fd5b600061010080838503121561427557600080fd5b6040519081019067ffffffffffffffff821181831017156142985761429861413a565b81604052835191506142a9826133d7565b8181526142b86020850161422c565b60208201526142c960408501614237565b60408201526142da60608501614237565b6060820152608084015160808201526142f560a08501614237565b60a082015260c084015160c082015261431060e08501614242565b60e0820152949350505050565b60006020828403121561432f57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261436b57600080fd5b830160208101925035905067ffffffffffffffff81111561438b57600080fd5b8060051b36038213156134ea57600080fd5b600481106143d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261440c57600080fd5b90910192915050565b60008383855260208086019550808560051b8301018460005b878110156144cd57601f1985840301895261444982886143d8565b60408085018235614459816133d7565b6001600160a01b0316865261447083880184614336565b8789019390935290829052909150606085019060005b838110156144b85781356004811061449d57600080fd5b6144a7848261439d565b509187019190870190600101614486565b5050998501999350509083019060010161442e565b5090979650505050505050565b60c0815260006144ee60c08301898b614415565b602083019790975250604081019490945260ff929092166060840152608083015260a09091015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261457e57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126145bd57600080fd5b83018035915067ffffffffffffffff8211156145d857600080fd5b6020019150600581901b36038213156134ea57600080fd5b60408082528181018490526000906060808401600587811b860183018986805b8b8110156146c6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652614649838e6143d8565b8035614654816133d7565b6001600160a01b03168552602061466d82820183614336565b92508a82880152828b8801527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146a5578485fd5b91871b918281888c0137509687019694018701939290920191600101614610565b5050506001600160a01b0388166020880152945061131e9350505050565b600067ffffffffffffffff8211156146fe576146fe61413a565b5060051b60200190565b6000602080838503121561471b57600080fd5b825167ffffffffffffffff81111561473257600080fd5b8301601f8101851361474357600080fd5b8051614756614751826146e4565b6141fb565b81815260059190911b8201830190838101908783111561477557600080fd5b928401925b8284101561094a5783518252928401929084019061477a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126147c857600080fd5b83018035915067ffffffffffffffff8211156147e357600080fd5b6020019150368190038213156134ea57600080fd5b60008151808452602080850194506020840160005b838110156148325781516001600160a01b03168752958201959082019060010161480d565b509495945050505050565b60008151808452602080850194506020840160005b83811015614832578151805160ff908116895290840151168388015260409096019590820190600101614852565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6080815260006148be60808301886147f8565b82810360208401526148d0818861483d565b9050851515604084015282810360608401526148ed818587614880565b98975050505050505050565b6000614907614751846146e4565b8381529050602080820190600785901b84018681111561492657600080fd5b845b818110156149a057608080828a0312156149425760008081fd5b604080519182019167ffffffffffffffff831181841017156149665761496661413a565b918152825191614975836133d7565b9182528285015185830152808301519082015260608083015190820152845292820192608001614928565b505050509392505050565b80517fff000000000000000000000000000000000000000000000000000000000000008116811461340957600080fd5b600060208083850312156149ee57600080fd5b825167ffffffffffffffff80821115614a0657600080fd5b81850191506040808388031215614a1c57600080fd5b614a24614169565b835183811115614a3357600080fd5b8401601f81018913614a4457600080fd5b614a528982518884016148f9565b8252508484015183811115614a6657600080fd5b80850194505087601f850112614a7b57600080fd5b83519250614a8b614751846146e4565b83815260e0938402850186019386820191908a861115614aaa57600080fd5b958701955b85871015614b335780878c031215614ac75760008081fd5b614acf614192565b8751614ada816133d7565b815287890151614ae9816133d7565b818a01528786015186820152606080890151908201526080808901519082015260a0808901519082015260c0614b20818a016149ab565b9082015283529586019591870191614aaf565b5095820195909552979650505050505050565b604081526000614b5960408301856147f8565b8281036020840152610afa818561483d565b60006020808385031215614b7e57600080fd5b825167ffffffffffffffff80821115614b9657600080fd5b81850191506040808388031215614bac57600080fd5b614bb4614169565b835183811115614bc357600080fd5b8401601f81018913614bd457600080fd5b614be28982518884016148f9565b8252508484015183811115614bf657600080fd5b80850194505087601f850112614c0b57600080fd5b83519250614c1b614751846146e4565b83815260a0938402850186019386820191908a861115614c3a57600080fd5b958701955b85871015614b335780878c031215614c575760008081fd5b614c5f6141b5565b8751614c6a816133d7565b815287890151614c79816133d7565b818a01528786015186820152606080890151908201526080614c9c818a016149ab565b9082015283529586019591870191614c3f565b60008060408385031215614cc257600080fd5b505080516020909101519092909150565b60a08082528101869052600060c0600588901b8301810190830189835b8a811015614d67577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40868503018352614d29828d6143d8565b6040813586526020614d3d81840184614336565b93508282890152614d518389018583614415565b9750509485019493909301925050600101614cf0565b5050506020830187905260ff861660408401529050606082019390935260800152949350505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106c7576106c7614da0565b602081526000610eff60208301846136fa565b60006001600160a01b03808b168352808a16602084015288604084015263ffffffff808916606085015280881660808501525080861660a08401525060e060c0830152614e4660e083018486614415565b9a9950505050505050505050565b6001600160a01b038b811682528a81166020830152604082018a905263ffffffff898116606084015288166080830152861660a082015261010060c08201819052600090614ea58382018789614415565b905082810360e0840152614eba818587614880565b9d9c50505050505050505050505050565b600060208284031215614edd57600080fd5b8151610eff816133d7565b8381526001600160a01b03831660208201526060810161131e604083018461439d565b600060208284031215614f1d57600080fd5b8151610eff8161382d565b60208152600061131e602083018486614880565b6000825161457e8184602087016136aa565b60006020808385031215614f6157600080fd5b825167ffffffffffffffff80821115614f7957600080fd5b9084019060608287031215614f8d57600080fd5b614f956141d8565b8251614fa08161382d565b81528284015182811115614fb357600080fd5b8301601f81018813614fc457600080fd5b805183811115614fd657614fd661413a565b614fe886601f19601f840116016141fb565b93508084528886828401011115614ffe57600080fd5b61500d818786018885016136aa565b505092830152604090810151908201529392505050565b60006040828403121561503657600080fd5b61503e614169565b8235615049816133d7565b81526020928301359281019290925250919050565b60008151808452602080850194506020840160005b838110156148325761509987835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101615073565b60808152600060e08201875160606080850152818151808452610100860191506020935060208301925060005b81811015615112576150ff83855180516001600160a01b03168252602090810151910152565b92840192604092909201916001016150d9565b505060208a015160a086015260408a015160c0860152848103602086015261513a818a61505e565b9250505061515360408401876001600160a01b03169052565b82810360608401526148ed818587614880565b600061010061518983895180516001600160a01b03168252602090810151910152565b60208801516040840152604088015160608401526151bd608084018880516001600160a01b03168252602090810151910152565b6001600160a01b03861660c08401528060e08401526148ed8184018587614880565b6000604082840312156151f157600080fd5b6151f9614169565b8235615204816133d7565b81526020830135615214816133d7565b60208201529392505050565b60006020828403121561523257600080fd5b610eff826149ab565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461340957600080fd5b6000806000806080858703121561527d57600080fd5b8451615288816133ec565b93506152966020860161523b565b925060408501516152a6816133ec565b91506152b46060860161523b565b905092959194509250565b600063ffffffff808416806152fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b63ffffffff818116838216019080821115610bf957610bf9614da0565b63ffffffff81811683821602808216919082811461534657615346614da0565b505092915050565b808201808211156106c7576106c7614da0565b80820281158282048414176106c7576106c7614da0565b6000600019820361538b5761538b614da0565b5060010190565b6000816153a1576153a1614da0565b506000190190565b60ff81811683821601908111156106c7576106c7614da0565b600060ff821660ff81036153d8576153d8614da0565b6001019291505056000000000000000000000000ed306e38bb930ec9646ff3d917b2e513a97530b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce9f6991b48970d6c9ef99fffb112359584488e3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Deployed Bytecode
0x60806040526004361061021d5760003560e01c806362b850c71161011d578063bcbef206116100b0578063e3056a341161007f578063effca70511610064578063effca705146105e1578063f235757f14610601578063fa0c95551461062157600080fd5b8063e3056a3414610592578063e43581b8146105b257600080fd5b8063bcbef2061461052a578063d9a673ef1461053d578063db8266de14610550578063df08aed51461056357600080fd5b8063910cab11116100ec578063910cab11146104b7578063a669a7f6146104d7578063ac9650d8146104ea578063bb2871a51461050a57600080fd5b806362b850c71461044a57806362dd9af31461045d5780636afdd8501461047057806389352328146104a457600080fd5b806335ac2a50116101b057806340c5710c1161017f5780635684c275116101645780635684c275146103cd578063585cc6a5146103fa5780635f963dcf1461042257600080fd5b806340c5710c1461038d578063484b3577146103a057600080fd5b806335ac2a501461032757806337b0c09d146103475780633a79d6741461035a5780633ed242b41461036d57600080fd5b80631f66925c116101ec5780631f66925c146102c05780631f8b479d146102e15780632b3297f9146102f4578063340b532f1461031457600080fd5b806301ffc9a71461022957806305ce20d61461025e5780630c340a241461027357806313f6986d146102ab57600080fd5b3661022457005b600080fd5b34801561023557600080fd5b50610249610244366004613395565b610634565b60405190151581526020015b60405180910390f35b61027161026c36600461340e565b6106cd565b005b34801561027f57600080fd5b50600054610293906001600160a01b031681565b6040516001600160a01b039091168152602001610255565b3480156102b757600080fd5b50610271610801565b6102d36102ce366004613463565b6108ad565b604051908152602001610255565b6102716102ef366004613502565b610955565b34801561030057600080fd5b50600254610293906001600160a01b031681565b61027161032236600461358e565b6109a6565b61033a6103353660046135c7565b6109b4565b6040516102559190613624565b610271610355366004613463565b610b03565b610271610368366004613463565b610b1d565b61038061037b366004613668565b610b28565b604051610255919061372f565b61027161039b3660046137b1565b610c00565b3480156103ac57600080fd5b506103c06103bb36600461387d565b610d83565b6040516102559190613914565b3480156103d957600080fd5b506103ed6103e8366004613a45565b610e48565b6040516102559190613a9a565b34801561040657600080fd5b5061029373eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b610435610430366004613ba8565b610f06565b60408051928352602083019190915201610255565b610271610458366004613bf0565b610fbb565b61027161046b366004613c87565b610ffd565b34801561047c57600080fd5b506102937f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba381565b6102d36104b2366004613d0a565b611087565b3480156104c357600080fd5b50600354610293906001600160a01b031681565b6102d36104e5366004613deb565b611132565b6104fd6104f8366004613668565b61122d565b6040516102559190613e5f565b34801561051657600080fd5b5061033a610525366004613ed4565b611310565b610271610538366004613f31565b611326565b61027161054b366004613f67565b6113f5565b61027161055e366004613fde565b61142e565b34801561056f57600080fd5b5061024961057e36600461402f565b6001546001600160a01b0391821691161490565b34801561059e57600080fd5b50600154610293906001600160a01b031681565b3480156105be57600080fd5b506102496105cd36600461402f565b6000546001600160a01b0391821691161490565b3480156105ed57600080fd5b506102716105fc36600461358e565b61149e565b34801561060d57600080fd5b5061027161061c36600461402f565b611528565b6102d361062f36600461404c565b6115d8565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f3ed242b40000000000000000000000000000000000000000000000000000000014806106c757507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b838360006106dc83838361171f565b6040517f5b6fd01d000000000000000000000000000000000000000000000000000000008152600481018790526000906001600160a01b03891690635b6fd01d9060240161010060405180830381865afa15801561073e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107629190614261565b519050610770818988611827565b6040517fded700a6000000000000000000000000000000000000000000000000000000008152600481018890526024810187905263ffffffff861660448201526001600160a01b0389169063ded700a6906064015b600060405180830381600087803b1580156107df57600080fd5b505af11580156107f3573d6000803e3d6000fd5b505050505050505050505050565b6001546001600160a01b03163314610845576040517f9ba0305d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018054600080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b0384161782559091169091556040517fdc57ca23c46d823853915ed5a090ca0ee9db5eb6a46f5c58e1c9158de861fd769190a1565b6000838360026108be83838361171f565b6040517f17621890000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301528816906317621890906044016020604051808303816000875af1158015610926573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a919061431d565b979650505050505050565b6040517f4faa38830000000000000000000000000000000000000000000000000000000081526001600160a01b03891690634faa3883906107c5908a908a908a908a908a908a908a906004016144da565b6109b082826118da565b5050565b606060005b83811015610a695760008585838181106109d5576109d561451b565b90506020028101906109e7919061454a565b6109f5906020810190614588565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394505050505b8151811015610a5f57610a5788838381518110610a4857610a4861451b565b6020026020010151600261171f565b600101610a29565b50506001016109b9565b506040517f480b37960000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063480b379690610ab3908790879087906004016145f0565b6000604051808303816000875af1158015610ad2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610afa9190810190614708565b95945050505050565b610b186001600160a01b03841633838561199b565b505050565b610b18838383611a17565b60608167ffffffffffffffff811115610b4357610b4361413a565b604051908082528060200260200182016040528015610b9a57816020015b610b87604051806060016040528060001515815260200160608152602001600081525090565b815260200190600190039081610b615790505b50905060005b82811015610bf957610bd4848483818110610bbd57610bbd61451b565b9050602002810190610bcf9190614793565b611a7f565b828281518110610be657610be661451b565b6020908102919091010152600101610ba0565b5092915050565b82826000610c0f83838361171f565b6040517f5b6fd01d000000000000000000000000000000000000000000000000000000008152600481018690526000906001600160a01b03881690635b6fd01d9060240161010060405180830381865afa158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614261565b516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610cf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1d919061431d565b9050610d2a828983611827565b6040517fded700a6000000000000000000000000000000000000000000000000000000008152600481018890526024810182905263ffffffff871660448201526001600160a01b0389169063ded700a6906064016107c5565b6040805180820190915260608082526020820152600080610da48888611bff565b6040517f4997cdc300000000000000000000000000000000000000000000000000000000815291935091506001600160a01b038a1690634997cdc390610df690859085908b908b908b906004016148ab565b600060405180830381865afa158015610e13573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e3b91908101906149db565b9998505050505050505050565b6040805180820190915260608082526020820152600080610e698585611bff565b6040517fd2d95b2d00000000000000000000000000000000000000000000000000000000815291935091506001600160a01b0387169063d2d95b2d90610eb59085908590600401614b46565b600060405180830381865afa158015610ed2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610efa9190810190614b6b565b925050505b9392505050565b60008085856003610f1883838361171f565b6040517f72ada4c5000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b03888116602483015287811660448301528a16906372ada4c59060640160408051808303816000875af1158015610f87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fab9190614caf565b909a909950975050505050505050565b610ff46001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31688888888888888611c60565b50505050505050565b6040517f3dff05870000000000000000000000000000000000000000000000000000000081526001600160a01b03881690633dff05879061104c90899089908990899089908990600401614cd3565b600060405180830381600087803b15801561106657600080fd5b505af115801561107a573d6000803e3d6000fd5b5050505050505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009081906001600160a01b038c16906370a0823190602401602060405180830381865afa1580156110e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110d919061431d565b90506111228c8c8c848d8d8d8d8d8d8d6115d8565b9c9b505050505050505050505050565b60006001600160a01b0386161561115f5760035461115f906001600160a01b038881169116600019611d1a565b600254611177906001600160a01b0316858588611dd8565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611221576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156111f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121c919061431d565b611223565b475b9695505050505050565b60608167ffffffffffffffff8111156112485761124861413a565b60405190808252806020026020018201604052801561127b57816020015b60608152602001906001900390816112665790505b50905060005b82811015610bf9576112eb3085858481811061129f5761129f61451b565b90506020028101906112b19190614793565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e2a92505050565b8282815181106112fd576112fd61451b565b6020908102919091010152600101611281565b6060610afa85858585611e97565b949350505050565b60005a9050600080306001600160a01b03168585604051611348929190614d90565b600060405180830381855af49150503d8060008114611383576040519150601f19603f3d011682016040523d82523d6000602084013e611388565b606091505b509150915060005a61139a9085614dcf565b905060405180606001604052808415158152602001838152602001828152506040517f493703af0000000000000000000000000000000000000000000000000000000081526004016113ec9190614de2565b60405180910390fd5b610ff46001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31688888888888888611f73565b8484600161143d83838361171f565b6040517ff1accf39000000000000000000000000000000000000000000000000000000008152600481018890526024810187905263ffffffff861660448201526001600160a01b03858116606483015289169063f1accf39906084016107c5565b6000546001600160a01b031633146114e2576040517fe0a8b92000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280546001600160a01b039384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560038054929093169116179055565b6000546001600160a01b0316331461156c576040517fe0a8b92000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f56bddfa0cee9697cebddf9acd7f23dc6583663b05e007b877056d05017994def9060200160405180910390a150565b60006115e58b8d8b611827565b81611685576040517f6b29e1bd0000000000000000000000000000000000000000000000000000000081526001600160a01b038d1690636b29e1bd9061163d908e908e908e908e908e908e908e908e90600401614df5565b6020604051808303816000875af115801561165c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611680919061431d565b611122565b6040517fb2b513c10000000000000000000000000000000000000000000000000000000081526001600160a01b038d169063b2b513c1906116dc908e908e908e908e908e908e908e908e908e908e90600401614e54565b6020604051808303816000875af11580156116fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611122919061431d565b826001600160a01b031663cc7a20496040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117819190614ecb565b6001600160a01b031663823abfd98333846040518463ffffffff1660e01b81526004016117b093929190614ee8565b602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f19190614f0b565b610b18576040517f5c427cd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b4919061431d565b9050818110156118d4576118d46001600160a01b03851684600019611d1a565b50505050565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611986576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611981919061431d565b611988565b475b90508015610b1857610b18838284611a17565b6040516001600160a01b0384811660248301528381166044830152606482018390526118d49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611ffc565b6001600160a01b038116611a285750335b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6b57610b186001600160a01b03821683612078565b610b186001600160a01b0384168284612141565b611aa5604051806060016040528060001515815260200160608152602001600081525090565b600080306001600160a01b031663bcbef20660e01b8686604051602401611acd929190614f28565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611b389190614f3c565b600060405180830381855af49150503d8060008114611b73576040519150601f19603f3d011682016040523d82523d6000602084013e611b78565b606091505b50915091508115611be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5754463f2053686f756c642068617665206661696c656421000000000000000060448201526064016113ec565b60048101905080806020019051810190610afa9190614f4e565b606080611c5484846000604051908082528060200260200182016040528015611c4e57816020015b6040805180820190915260008082526020820152815260200190600190039081611c275790505b50612172565b50909590945092505050565b8515611d1057876001600160a01b031663edd9444b60405180606001604052808a8a808060200260200160405190810160405280939291908181526020016000905b82821015611cce57611cbf60408302860136819003810190615024565b81526020019060010190611ca2565b5050505050815260200188815260200187815250611ced8a8a866121f7565b3387876040518663ffffffff1660e01b81526004016107c59594939291906150ac565b5050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611d9984826122cc565b6118d4576040516001600160a01b03848116602483015260006044830152611dce91869182169063095ea7b3906064016119d0565b6118d48482611ffc565b611e2383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b0387169190508361236f565b5050505050565b6060600080846001600160a01b031684604051611e479190614f3c565b600060405180830381855af49150503d8060008114611e82576040519150601f19603f3d011682016040523d82523d6000602084013e611e87565b606091505b5091509150610afa858383612417565b60608267ffffffffffffffff811115611eb257611eb261413a565b604051908082528060200260200182016040528015611edb578160200160208202803683370190505b50905060005b83811015611f6a57611f4586868684818110611eff57611eff61451b565b611f15926020604090920201908101915061402f565b878785818110611f2757611f2761451b565b9050604002016020016020810190611f3f919061402f565b8661248c565b828281518110611f5757611f5761451b565b6020908102919091010152600101611ee1565b50949350505050565b6040805160a0810182526001600160a01b0389811660608301908152608083018a9052825260208083018990528284018890528351808501855285831681529081018a905292517f30f28b7a000000000000000000000000000000000000000000000000000000008152908b16926330f28b7a926107c592909190339089908990600401615166565b60006120116001600160a01b03841683612803565b905080516000141580156120365750808060200190518101906120349190614f0b565b155b15610b18576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016113ec565b804710156120b4576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016113ec565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612101576040519150601f19603f3d011682016040523d82523d6000602084013e612106565b606091505b5050905080610b18576040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03838116602483015260448201839052610b1891859182169063a9059cbb906064016119d0565b60608060606121d38686808060200260200160405190810160405280939291908181526020016000905b828210156121c8576121b9604083028601368190038101906151df565b8152602001906001019061219c565b505050505085612811565b92506121e0868685612ccd565b91506121ec8484612f5e565b905093509350939050565b60608267ffffffffffffffff8111156122125761221261413a565b60405190808252806020026020018201604052801561225757816020015b60408051808201909152600080825260208201528152602001906001900390816122305790505b50905060005b81518110156122c4576040518060400160405280846001600160a01b031681526020018686848181106122925761229261451b565b905060400201602001358152508282815181106122b1576122b161451b565b602090810291909101015260010161225d565b509392505050565b6000806000846001600160a01b0316846040516122e99190614f3c565b6000604051808303816000865af19150503d8060008114612326576040519150601f19603f3d011682016040523d82523d6000602084013e61232b565b606091505b50915091508180156123555750805115806123555750808060200190518101906123559190614f0b565b8015610afa5750505050506001600160a01b03163b151590565b6060814710156123ad576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016113ec565b600080856001600160a01b031684866040516123c99190614f3c565b60006040518083038185875af1925050503d8060008114612406576040519150601f19603f3d011682016040523d82523d6000602084013e61240b565b606091505b5091509150610efa8683835b60608261242c576124278261305a565b610eff565b815115801561244357506001600160a01b0384163b155b15612485576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016113ec565b5080610eff565b600080600061249b868661309f565b6040517f582cf84b0000000000000000000000000000000000000000000000000000000081526001600160a01b038084166004830152808316602483015292945090925060009189169063582cf84b90604401602060405180830381865afa15801561250b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252f9190615220565b90507f010000000000000000000000000000000000000000000000000000000000000060005b7fff00000000000000000000000000000000000000000000000000000000000000808316908416108015906125ab57507fff00000000000000000000000000000000000000000000000000000000000000821615155b156127f257817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168284167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036127c4576040517f808ba8e00000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015289811660248301527fff000000000000000000000000000000000000000000000000000000000000008416604483015260009182918291908e169063808ba8e090606401608060405180830381865afa158015612694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b89190615267565b9350935093505060006126ca866130d0565b90506000816126d981866152bf565b6126e4906001615309565b6126ee9190615326565b63ffffffff1690508b612719576127066003836152bf565b6127169063ffffffff168261534e565b90505b6000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16118061276457506000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16115b1561279d5742811161278257859a505050505050505050505061131e565b61278c4282614dcf565b9a505050505050505050505061131e565b428111156127be5785156127b157856127bb565b6127bb4282614dcf565b95505b50505050505b6001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901b9150612555565b506000199998505050505050505050565b6060610eff8383600061236f565b60606000808351855160026128269190615361565b612830919061534e565b67ffffffffffffffff8111156128485761284861413a565b604051908082528060200260200182016040528015612871578160200160208202803683370190505b50905060005b8551811015612a405760008060005b858110801561289c575082801561289a5750815b155b1561297157821580156128f657508884815181106128bc576128bc61451b565b6020026020010151600001516001600160a01b03168582815181106128e3576128e361451b565b60200260200101516001600160a01b0316145b1561290057600192505b81158015612955575088848151811061291b5761291b61451b565b6020026020010151602001516001600160a01b03168582815181106129425761294261451b565b60200260200101516001600160a01b0316145b1561295f57600191505b8061296981615378565b915050612886565b50816129d4578783815181106129895761298961451b565b6020026020010151600001518486806129a190615378565b9750815181106129b3576129b361451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b80612a36578783815181106129eb576129eb61451b565b602002602001015160200151848680612a0390615378565b975081518110612a1557612a1561451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101612877565b5060005b8451811015612b35576000805b8481108015612a5e575081155b15612ac957868381518110612a7557612a7561451b565b6020026020010151600001516001600160a01b0316848281518110612a9c57612a9c61451b565b60200260200101516001600160a01b031603612ab757600191505b80612ac181615378565b915050612a51565b5080612b2c57858281518110612ae157612ae161451b565b602002602001015160000151838580612af990615378565b965081518110612b0b57612b0b61451b565b60200260200101906001600160a01b031690816001600160a01b0316815250505b50600101612a44565b508167ffffffffffffffff811115612b4f57612b4f61413a565b604051908082528060200260200182016040528015612b78578160200160208202803683370190505b50925060005b82811015612cc4576000828281518110612b9a57612b9a61451b565b6020026020010151905060005b816001600160a01b0316868281518110612bc357612bc361451b565b60200260200101516001600160a01b0316108015612c0d575060006001600160a01b0316868281518110612bf957612bf961451b565b60200260200101516001600160a01b031614155b15612c245780612c1c81615378565b915050612ba7565b825b81811115612c8e5786612c3a600183614dcf565b81518110612c4a57612c4a61451b565b6020026020010151878281518110612c6457612c6461451b565b6001600160a01b039092166020928302919091019091015280612c8681615392565b915050612c26565b5081868281518110612ca257612ca261451b565b6001600160a01b03909216602092830291909101909101525050600101612b7e565b50505092915050565b60608267ffffffffffffffff811115612ce857612ce861413a565b604051908082528060200260200182016040528015612d2d57816020015b6040805180820190915260008082526020820152815260200190600190039081612d065790505b5090506000805b83518160ff161015612f55576000612d4d8260016153a9565b90505b84518160ff161015612f425760005b86811015612f2f57878782818110612d7957612d7961451b565b612d8f926020604090920201908101915061402f565b6001600160a01b0316868460ff1681518110612dad57612dad61451b565b60200260200101516001600160a01b0316148015612e215750878782818110612dd857612dd861451b565b9050604002016020016020810190612df0919061402f565b6001600160a01b0316868360ff1681518110612e0e57612e0e61451b565b60200260200101516001600160a01b0316145b80612ee15750878782818110612e3957612e3961451b565b9050604002016020016020810190612e51919061402f565b6001600160a01b0316868460ff1681518110612e6f57612e6f61451b565b60200260200101516001600160a01b0316148015612ee15750878782818110612e9a57612e9a61451b565b612eb0926020604090920201908101915061402f565b6001600160a01b0316868360ff1681518110612ece57612ece61451b565b60200260200101516001600160a01b0316145b15612f27576040805180820190915260ff8085168252831660208201528585612f0981615378565b965081518110612f1b57612f1b61451b565b60200260200101819052505b600101612d5f565b5080612f3a816153c2565b915050612d50565b5080612f4d816153c2565b915050612d34565b50509392505050565b6060815167ffffffffffffffff811115612f7a57612f7a61413a565b604051908082528060200260200182016040528015612fa3578160200160208202803683370190505b50905060005b8351811015610bf95760005b848281518110612fc757612fc761451b565b6020026020010151600001516001600160a01b0316848281518110612fee57612fee61451b565b60200260200101516001600160a01b031614613016578061300e81615378565b915050612fb5565b8482815181106130285761302861451b565b6020026020010151602001518382815181106130465761304661451b565b602090810291909101015250600101612fa9565b80511561306a5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600080826001600160a01b0316846001600160a01b0316106130c25782846130c5565b83835b909590945092505050565b60007fff0000000000000000000000000000000000000000000000000000000000000082167f0100000000000000000000000000000000000000000000000000000000000000036131235750603c919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f020000000000000000000000000000000000000000000000000000000000000003613175575061012c919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f0400000000000000000000000000000000000000000000000000000000000000036131c75750610384919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f0800000000000000000000000000000000000000000000000000000000000000036132195750610708919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f10000000000000000000000000000000000000000000000000000000000000000361326b5750610e10919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f2000000000000000000000000000000000000000000000000000000000000000036132bd5750613840919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f400000000000000000000000000000000000000000000000000000000000000003613310575062015180919050565b7fff0000000000000000000000000000000000000000000000000000000000000082167f800000000000000000000000000000000000000000000000000000000000000003613363575062093a80919050565b6040517fbf3cad0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156133a757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eff57600080fd5b6001600160a01b038116811461309c57600080fd5b63ffffffff8116811461309c57600080fd5b8035613409816133ec565b919050565b6000806000806080858703121561342457600080fd5b843561342f816133d7565b93506020850135925060408501359150606085013561344d816133ec565b939692955090935050565b8035613409816133d7565b60008060006060848603121561347857600080fd5b8335613483816133d7565b925060208401359150604084013561349a816133d7565b809150509250925092565b60008083601f8401126134b757600080fd5b50813567ffffffffffffffff8111156134cf57600080fd5b6020830191508360208260051b85010111156134ea57600080fd5b9250929050565b803560ff8116811461340957600080fd5b60008060008060008060008060e0898b03121561351e57600080fd5b8835613529816133d7565b9750602089013567ffffffffffffffff81111561354557600080fd5b6135518b828c016134a5565b909850965050604089013594506060890135935061357160808a016134f1565b925060a0890135915060c089013590509295985092959890939650565b600080604083850312156135a157600080fd5b82356135ac816133d7565b915060208301356135bc816133d7565b809150509250929050565b600080600080606085870312156135dd57600080fd5b84356135e8816133d7565b9350602085013567ffffffffffffffff81111561360457600080fd5b613610878288016134a5565b909450925050604085013561344d816133d7565b6020808252825182820181905260009190848201906040850190845b8181101561365c57835183529284019291840191600101613640565b50909695505050505050565b6000806020838503121561367b57600080fd5b823567ffffffffffffffff81111561369257600080fd5b61369e858286016134a5565b90969095509350505050565b60005b838110156136c55781810151838201526020016136ad565b50506000910152565b600081518084526136e68160208601602086016136aa565b601f01601f19169290920160200192915050565b805115158252600060208201516060602085015261371b60608501826136ce565b604093840151949093019390935250919050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156137a4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526137928583516136fa565b94509285019290850190600101613758565b5092979650505050505050565b6000806000606084860312156137c657600080fd5b83356137d1816133d7565b925060208401359150604084013561349a816133ec565b60008083601f8401126137fa57600080fd5b50813567ffffffffffffffff81111561381257600080fd5b6020830191508360208260061b85010111156134ea57600080fd5b801515811461309c57600080fd5b60008083601f84011261384d57600080fd5b50813567ffffffffffffffff81111561386557600080fd5b6020830191508360208285010111156134ea57600080fd5b6000806000806000806080878903121561389657600080fd5b86356138a1816133d7565b9550602087013567ffffffffffffffff808211156138be57600080fd5b6138ca8a838b016137e8565b9097509550604089013591506138df8261382d565b909350606088013590808211156138f557600080fd5b5061390289828a0161383b565b979a9699509497509295939492505050565b60006020808352606080840185516040808588015282825180855260809450608089019150868401935060005b8181101561398e5761397e8386516001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b9387019391850191600101613941565b505088860151888203601f190160408a0152805180835290870193506000918701905b80831015613a3757845180516001600160a01b03908116845289820151168984015284810151858401528781015188840152868101518784015260a0808201519084015260c0908101517fff000000000000000000000000000000000000000000000000000000000000001690830152938701936001929092019160e0909101906139b1565b509998505050505050505050565b600080600060408486031215613a5a57600080fd5b8335613a65816133d7565b9250602084013567ffffffffffffffff811115613a8157600080fd5b613a8d868287016137e8565b9497909650939450505050565b60006020808352606080840185516040808588015282825180855260809450608089019150868401935060005b81811015613b1457613b048386516001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b9387019391850191600101613ac7565b505088860151888203601f190160408a0152805180835290870193506000918701905b80831015613a3757845180516001600160a01b039081168452898201511689840152848101518584015287810151888401528601517fff000000000000000000000000000000000000000000000000000000000000001686830152938701936001929092019160a090910190613b37565b60008060008060808587031215613bbe57600080fd5b8435613bc9816133d7565b9350602085013592506040850135613be0816133d7565b9150606085013561344d816133d7565b600080600080600080600060a0888a031215613c0b57600080fd5b873567ffffffffffffffff80821115613c2357600080fd5b613c2f8b838c016137e8565b909950975060208a0135965060408a0135955060608a0135915080821115613c5657600080fd5b50613c638a828b0161383b565b9094509250506080880135613c77816133d7565b8091505092959891949750929550565b600080600080600080600060c0888a031215613ca257600080fd5b8735613cad816133d7565b9650602088013567ffffffffffffffff811115613cc957600080fd5b613cd58a828b016134a5565b90975095505060408801359350613cee606089016134f1565b92506080880135915060a0880135905092959891949750929550565b6000806000806000806000806000806101008b8d031215613d2a57600080fd5b8a35613d35816133d7565b995060208b0135613d45816133d7565b985060408b0135613d55816133d7565b975060608b0135613d65816133ec565b965060808b0135613d75816133ec565b9550613d8360a08c01613458565b945060c08b013567ffffffffffffffff80821115613da057600080fd5b613dac8e838f016134a5565b909650945060e08d0135915080821115613dc557600080fd5b50613dd28d828e0161383b565b915080935050809150509295989b9194979a5092959850565b600080600080600060808688031215613e0357600080fd5b8535613e0e816133d7565b945060208601359350604086013567ffffffffffffffff811115613e3157600080fd5b613e3d8882890161383b565b9094509250506060860135613e51816133d7565b809150509295509295909350565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156137a4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613ec28583516136ce565b94509285019290850190600101613e88565b60008060008060608587031215613eea57600080fd5b8435613ef5816133d7565b9350602085013567ffffffffffffffff811115613f1157600080fd5b613f1d878288016137e8565b909450925050604085013561344d8161382d565b60008060208385031215613f4457600080fd5b823567ffffffffffffffff811115613f5b57600080fd5b61369e8582860161383b565b600080600080600080600060c0888a031215613f8257600080fd5b8735613f8d816133d7565b9650602088013595506040880135945060608801359350608088013567ffffffffffffffff811115613fbe57600080fd5b613fca8a828b0161383b565b90945092505060a0880135613c77816133d7565b600080600080600060a08688031215613ff657600080fd5b8535614001816133d7565b94506020860135935060408601359250606086013561401f816133ec565b91506080860135613e51816133d7565b60006020828403121561404157600080fd5b8135610eff816133d7565b60008060008060008060008060008060006101208c8e03121561406e57600080fd5b6140788c356133d7565b8b359a5061408960208d01356133d7565b60208c0135995061409c60408d01613458565b985060608c013597506140b160808d016133fe565b96506140bf60a08d016133fe565b95506140cd60c08d01613458565b945067ffffffffffffffff8060e08e013511156140e957600080fd5b6140f98e60e08f01358f016134a5565b90955093506101008d013581101561411057600080fd5b506141228d6101008e01358e0161383b565b81935080925050509295989b509295989b9093969950565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561418c5761418c61413a565b60405290565b60405160e0810167ffffffffffffffff8111828210171561418c5761418c61413a565b60405160a0810167ffffffffffffffff8111828210171561418c5761418c61413a565b6040516060810167ffffffffffffffff8111828210171561418c5761418c61413a565b604051601f8201601f1916810167ffffffffffffffff811182821017156142245761422461413a565b604052919050565b8051613409816133d7565b8051613409816133ec565b80516effffffffffffffffffffffffffffff8116811461340957600080fd5b600061010080838503121561427557600080fd5b6040519081019067ffffffffffffffff821181831017156142985761429861413a565b81604052835191506142a9826133d7565b8181526142b86020850161422c565b60208201526142c960408501614237565b60408201526142da60608501614237565b6060820152608084015160808201526142f560a08501614237565b60a082015260c084015160c082015261431060e08501614242565b60e0820152949350505050565b60006020828403121561432f57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261436b57600080fd5b830160208101925035905067ffffffffffffffff81111561438b57600080fd5b8060051b36038213156134ea57600080fd5b600481106143d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261440c57600080fd5b90910192915050565b60008383855260208086019550808560051b8301018460005b878110156144cd57601f1985840301895261444982886143d8565b60408085018235614459816133d7565b6001600160a01b0316865261447083880184614336565b8789019390935290829052909150606085019060005b838110156144b85781356004811061449d57600080fd5b6144a7848261439d565b509187019190870190600101614486565b5050998501999350509083019060010161442e565b5090979650505050505050565b60c0815260006144ee60c08301898b614415565b602083019790975250604081019490945260ff929092166060840152608083015260a09091015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261457e57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126145bd57600080fd5b83018035915067ffffffffffffffff8211156145d857600080fd5b6020019150600581901b36038213156134ea57600080fd5b60408082528181018490526000906060808401600587811b860183018986805b8b8110156146c6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652614649838e6143d8565b8035614654816133d7565b6001600160a01b03168552602061466d82820183614336565b92508a82880152828b8801527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146a5578485fd5b91871b918281888c0137509687019694018701939290920191600101614610565b5050506001600160a01b0388166020880152945061131e9350505050565b600067ffffffffffffffff8211156146fe576146fe61413a565b5060051b60200190565b6000602080838503121561471b57600080fd5b825167ffffffffffffffff81111561473257600080fd5b8301601f8101851361474357600080fd5b8051614756614751826146e4565b6141fb565b81815260059190911b8201830190838101908783111561477557600080fd5b928401925b8284101561094a5783518252928401929084019061477a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126147c857600080fd5b83018035915067ffffffffffffffff8211156147e357600080fd5b6020019150368190038213156134ea57600080fd5b60008151808452602080850194506020840160005b838110156148325781516001600160a01b03168752958201959082019060010161480d565b509495945050505050565b60008151808452602080850194506020840160005b83811015614832578151805160ff908116895290840151168388015260409096019590820190600101614852565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6080815260006148be60808301886147f8565b82810360208401526148d0818861483d565b9050851515604084015282810360608401526148ed818587614880565b98975050505050505050565b6000614907614751846146e4565b8381529050602080820190600785901b84018681111561492657600080fd5b845b818110156149a057608080828a0312156149425760008081fd5b604080519182019167ffffffffffffffff831181841017156149665761496661413a565b918152825191614975836133d7565b9182528285015185830152808301519082015260608083015190820152845292820192608001614928565b505050509392505050565b80517fff000000000000000000000000000000000000000000000000000000000000008116811461340957600080fd5b600060208083850312156149ee57600080fd5b825167ffffffffffffffff80821115614a0657600080fd5b81850191506040808388031215614a1c57600080fd5b614a24614169565b835183811115614a3357600080fd5b8401601f81018913614a4457600080fd5b614a528982518884016148f9565b8252508484015183811115614a6657600080fd5b80850194505087601f850112614a7b57600080fd5b83519250614a8b614751846146e4565b83815260e0938402850186019386820191908a861115614aaa57600080fd5b958701955b85871015614b335780878c031215614ac75760008081fd5b614acf614192565b8751614ada816133d7565b815287890151614ae9816133d7565b818a01528786015186820152606080890151908201526080808901519082015260a0808901519082015260c0614b20818a016149ab565b9082015283529586019591870191614aaf565b5095820195909552979650505050505050565b604081526000614b5960408301856147f8565b8281036020840152610afa818561483d565b60006020808385031215614b7e57600080fd5b825167ffffffffffffffff80821115614b9657600080fd5b81850191506040808388031215614bac57600080fd5b614bb4614169565b835183811115614bc357600080fd5b8401601f81018913614bd457600080fd5b614be28982518884016148f9565b8252508484015183811115614bf657600080fd5b80850194505087601f850112614c0b57600080fd5b83519250614c1b614751846146e4565b83815260a0938402850186019386820191908a861115614c3a57600080fd5b958701955b85871015614b335780878c031215614c575760008081fd5b614c5f6141b5565b8751614c6a816133d7565b815287890151614c79816133d7565b818a01528786015186820152606080890151908201526080614c9c818a016149ab565b9082015283529586019591870191614c3f565b60008060408385031215614cc257600080fd5b505080516020909101519092909150565b60a08082528101869052600060c0600588901b8301810190830189835b8a811015614d67577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40868503018352614d29828d6143d8565b6040813586526020614d3d81840184614336565b93508282890152614d518389018583614415565b9750509485019493909301925050600101614cf0565b5050506020830187905260ff861660408401529050606082019390935260800152949350505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106c7576106c7614da0565b602081526000610eff60208301846136fa565b60006001600160a01b03808b168352808a16602084015288604084015263ffffffff808916606085015280881660808501525080861660a08401525060e060c0830152614e4660e083018486614415565b9a9950505050505050505050565b6001600160a01b038b811682528a81166020830152604082018a905263ffffffff898116606084015288166080830152861660a082015261010060c08201819052600090614ea58382018789614415565b905082810360e0840152614eba818587614880565b9d9c50505050505050505050505050565b600060208284031215614edd57600080fd5b8151610eff816133d7565b8381526001600160a01b03831660208201526060810161131e604083018461439d565b600060208284031215614f1d57600080fd5b8151610eff8161382d565b60208152600061131e602083018486614880565b6000825161457e8184602087016136aa565b60006020808385031215614f6157600080fd5b825167ffffffffffffffff80821115614f7957600080fd5b9084019060608287031215614f8d57600080fd5b614f956141d8565b8251614fa08161382d565b81528284015182811115614fb357600080fd5b8301601f81018813614fc457600080fd5b805183811115614fd657614fd661413a565b614fe886601f19601f840116016141fb565b93508084528886828401011115614ffe57600080fd5b61500d818786018885016136aa565b505092830152604090810151908201529392505050565b60006040828403121561503657600080fd5b61503e614169565b8235615049816133d7565b81526020928301359281019290925250919050565b60008151808452602080850194506020840160005b838110156148325761509987835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101615073565b60808152600060e08201875160606080850152818151808452610100860191506020935060208301925060005b81811015615112576150ff83855180516001600160a01b03168252602090810151910152565b92840192604092909201916001016150d9565b505060208a015160a086015260408a015160c0860152848103602086015261513a818a61505e565b9250505061515360408401876001600160a01b03169052565b82810360608401526148ed818587614880565b600061010061518983895180516001600160a01b03168252602090810151910152565b60208801516040840152604088015160608401526151bd608084018880516001600160a01b03168252602090810151910152565b6001600160a01b03861660c08401528060e08401526148ed8184018587614880565b6000604082840312156151f157600080fd5b6151f9614169565b8235615204816133d7565b81526020830135615214816133d7565b60208201529392505050565b60006020828403121561523257600080fd5b610eff826149ab565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461340957600080fd5b6000806000806080858703121561527d57600080fd5b8451615288816133ec565b93506152966020860161523b565b925060408501516152a6816133ec565b91506152b46060860161523b565b905092959194509250565b600063ffffffff808416806152fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b63ffffffff818116838216019080821115610bf957610bf9614da0565b63ffffffff81811683821602808216919082811461534657615346614da0565b505092915050565b808201808211156106c7576106c7614da0565b80820281158282048414176106c7576106c7614da0565b6000600019820361538b5761538b614da0565b5060010190565b6000816153a1576153a1614da0565b506000190190565b60ff81811683821601908111156106c7576106c7614da0565b600060ff821660ff81036153d8576153d8614da0565b6001019291505056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ed306e38bb930ec9646ff3d917b2e513a97530b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce9f6991b48970d6c9ef99fffb112359584488e3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
-----Decoded View---------------
Arg [0] : _swapper (address): 0xED306e38BB930ec9646FF3D917B2e513a97530b1
Arg [1] : _allowanceTarget (address): 0x0000000000000000000000000000000000000000
Arg [2] : _governor (address): 0xCe9F6991b48970d6c9Ef99Fffb112359584488e3
Arg [3] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000ed306e38bb930ec9646ff3d917b2e513a97530b1
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 000000000000000000000000ce9f6991b48970d6c9ef99fffb112359584488e3
Arg [3] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.