// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.7.0; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "../utils/MappedSinglyLinkedList.sol"; import "./VolumeDrip.sol"; /// @title Manages the active set of Volume Drips. library VolumeDripManager { using SafeMathUpgradeable for uint256; using MappedSinglyLinkedList for MappedSinglyLinkedList.Mapping; using VolumeDrip for VolumeDrip.State; struct State { mapping(address => MappedSinglyLinkedList.Mapping) activeVolumeDrips; mapping(address => mapping(address => VolumeDrip.State)) volumeDrips; } /// @notice Activates a volume drip for the given (measure,dripToken) pair. /// @param self The VolumeDripManager state /// @param measure The measure token /// @param dripToken The drip token /// @param periodSeconds The period of the volume drip in seconds /// @param dripAmount The amount of tokens to drip each period /// @param endTime The end time to set for the current period. function activate( State storage self, address measure, address dripToken, uint32 periodSeconds, uint112 dripAmount, uint32 endTime ) internal returns (uint32) { require(!self.activeVolumeDrips[measure].contains(dripToken), "VolumeDripManager/drip-active"); if (self.activeVolumeDrips[measure].count == 0) { self.activeVolumeDrips[measure].initialize(); } self.activeVolumeDrips[measure].addAddress(dripToken); self.volumeDrips[measure][dripToken].setNewPeriod(periodSeconds, dripAmount, endTime); return self.volumeDrips[measure][dripToken].periodCount; } /// @notice Deactivates the volume drip for the given (measure, dripToken) pair. /// @param self The VolumeDripManager state /// @param measure The measure token /// @param dripToken The drip token /// @param prevDripToken The active drip token previous to the passed on in the list. function deactivate( State storage self, address measure, address dripToken, address prevDripToken ) internal { self.activeVolumeDrips[measure].removeAddress(prevDripToken, dripToken); } /// @notice Gets a list of active balance drip tokens /// @param self The BalanceDripManager state /// @param measure The measure token /// @return An array of Balance Drip token addresses function getActiveVolumeDrips(State storage self, address measure) internal view returns (address[] memory) { return self.activeVolumeDrips[measure].addressArray(); } /// @notice Sets the parameters for the next period of an active volume drip /// @param self The VolumeDripManager state /// @param measure The measure token /// @param dripToken The drip token /// @param periodSeconds The length in seconds to use for the next period /// @param dripAmount The amount of tokens to be dripped in the next period function set(State storage self, address measure, address dripToken, uint32 periodSeconds, uint112 dripAmount) internal { require(self.activeVolumeDrips[measure].contains(dripToken), "VolumeDripManager/drip-not-active"); self.volumeDrips[measure][dripToken].setNextPeriod(periodSeconds, dripAmount); } /// @notice Returns whether or not an active volume drip exists for the given (measure, dripToken) pair /// @param self The VolumeDripManager state /// @param measure The measure token /// @param dripToken The drip token function isActive(State storage self, address measure, address dripToken) internal view returns (bool) { return self.activeVolumeDrips[measure].contains(dripToken); } /// @notice Returns the VolumeDrip.State for the given (measure, dripToken) pair. /// @param self The VolumeDripManager state /// @param measure The measure token /// @param dripToken The drip token function getDrip(State storage self, address measure, address dripToken) internal view returns (VolumeDrip.State storage) { return self.volumeDrips[measure][dripToken]; } }