Gauge Controller Registry (Draft)

This document is a draft and likely to change.

The Gauge Controller Registry and the voting process it facilitates are crucial to the success and growth of the Neptune Mutual platform. By allowing the community to have a say in the allocation of NPM token emissions, Neptune Mutual fosters an environment where long-term commitment, collaboration, and innovation can thrive, ultimately leading to a more resilient and prosperous DeFi ecosystem.

The Gauge Controller Registry empowers the community to have an active role in the platform's governance and expansion. By allowing the listing of insurance pool PODs (Proof of Deposit) that currently exist in the Neptune Mutual marketplace, the Gauge Controller Registry ensures some of these pools are eligible to receive a portion of the NPM token block emissions as incentives.

Each month, the Neptune Mutual community comes together to cast their votes on proposals, determining which insurance pools should be allocated NPM emissions. This critical voting process unfolds through a decentralized Snapshot governance portal, guaranteeing transparency, fairness, and active community involvement in the decision-making. Once the community reaches a consensus, the GaugeControllerRegistry contract is updated on-chain using the setGaugefunction to reflect the new allocations accurately.

The gamified aspect of gauge voting introduces an element of excitement and engagement for the participants. It aligns the interests of the community with the platform's growth and success by encouraging users to become more actively involved. This innovative process allows third-party protocols to maximize their decentralized cover protection by incentivizing veNPM token holders to redirect a larger share of NPM token emissions to their insurance pools.

To achieve this, third-party protocols can offer their native tokens as rewards to veNPM token holders. This strategy not only encourages more NPM token emissions to be directed to their pool but also attracts more liquidity providers. As a result, the insurance pool becomes more robust, benefiting all stakeholders within the Neptune Mutual ecosystem.

The Gauge Controller Registry and its associated voting process play a vital role in fostering a dynamic, thriving, and interconnected ecosystem. By enabling users to vote on the allocation of NPM token emissions, Neptune Mutual creates a system that promotes long-term commitment, collaboration, and synergy between various protocols and projects within the DeFi space.

This democratic approach to governance ensures that the platform remains responsive to the needs of its users, allowing for adjustments and improvements as the DeFi landscape evolves. The gauge voting process also serves as a catalyst for innovation, enabling third-party protocols to find creative ways to engage and reward veNPM token holders in return for support and increased liquidity.

IGaugeControllerRegistry Interface Summary#

// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import "../../dependencies/interfaces/IVault.sol";

interface IGaugeControllerRegistry {
  struct PodArgs {
    IVault pod;
    uint256 lockupPeriodInBlocks;
    uint256 ratio;
  }

  struct PoolSetupArgs {
    string name;
    string info;
    uint256 platformFee;
    PodArgs staking;
  }

  struct Gauge {
    bytes32 key;
    uint256 emissionPerBlock;
  }

  function addOrEditPool(bytes32 key, PoolSetupArgs calldata args) external;
  function setGauge(uint256 epoch, uint256 amountToDeposit, Gauge[] calldata distribution) external;
  function withdrawRewards(bytes32 key, uint256 amount) external;
  function deactivatePool(bytes32 key) external;
  function activatePool(bytes32 key) external;
  function deletePool(bytes32 key) external;

  function isValid(bytes32 key) external view returns (bool);
  function isActive(bytes32 key) external view returns (bool);
  function get(bytes32 key) external view returns (PoolSetupArgs memory);
  function sumNpmDeposited() external view returns (uint256);
  function sumNpmWithdrawn() external view returns (uint256);
  function getLastEpoch() external view returns (uint256);
  function getEmissionPerBlock(bytes32 key) external view returns (uint256);
  function getAllocation(uint256 epoch) external view returns (uint256);

  event GaugeControllerRegistryOperatorSet(address previousOperator, address operator);
  event GaugeControllerRegistryRewardsWithdrawn(bytes32 key, uint256 amount);
  event GaugeControllerRegistryPoolAddedOrEdited(address indexed sender, bytes32 indexed key, PoolSetupArgs args);
  event GaugeControllerRegistryPoolDeactivated(address indexed sender, bytes32 indexed key);
  event GaugeControllerRegistryPoolActivated(address indexed sender, bytes32 indexed key);
  event GaugeControllerRegistryPoolDeleted(address indexed sender, bytes32 key);
  event GaugeSet(uint256 indexed epoch, uint256 distribution);
  event GaugeAllocationTransferred(uint256 indexed epoch, uint256 totalAllocation);

  error InvalidGaugeEpochError();
  error PoolNotFoundError(bytes32 key);
  error PoolNotActiveError(bytes32 key);
  error PoolDeactivatedError(bytes32 key);
  error PoolAlreadyDeactivatedError(bytes32 key);
  error PoolNotDeactivatedError(bytes32 key);
  error PoolAlreadyActiveError(bytes32 key);
  error PoolAlreadyExistsError(bytes32 key);
}

function initialize(address contractOwner, IStore protocolStore) external#

This function initializes the contract with the provided contract owner and protocol store address. It can only be called once, during the contract deployment.

Parameter Description
contractOwner Enter the address of the contract owner to set upon intialization.
protocolStore Enter the address of the protocol store to be used. The store instance will be used to get the NPM token address and protocol pausable status.

function addOrEditPool(bytes32 key, PoolSetupArgs calldata args) external#

This function allows the contract owner to add a new pool or edit an existing one. If the pool already exists, only the name and platform fee can be edited. If the pool is being added, all fields in the PoolSetupArgs must be provided.

Args Description
bytes32 key Enter the key of the pool
string name Enter the name of the pool
string info Enter the IPFS hash of the pool that contains metadata of this pool
uint256 platformFee Enter the fee charged by the protocol. Goes to the protocol treasury.
PodArgs staking IVault pod: enter the instance of the insurance pool POD to add. uint256 lockupPeriodInBlocks: enter a period in blocks to lock up the staked PODs. uint256 ratio: Enter the ratio as a fraction/percentage numerator of the const denominator value of 10000.

It will throw an error if:

  • The contract is paused
  • The provided pool key already exists when adding a new pool
  • The provided pool key does not exist when editing an existing pool
  • The pool is not active when editing an existing pool
  • The provided pool name is empty when adding a new pool
  • The provided pool POD address is a zero address when adding a new pool

function setGauge(uint256 epoch, uint256 amountToDeposit, Gauge[] calldata distribution) external#

This function allows the contract owner to set the gauge for an epoch with the provided amount to deposit and the distribution of the emissions per block for each pool. It can only be called by the contract owner.

Parameter Description
uint256 epoch The epoch number for which the gauge is being set
uint256 amountToDeposit The amount of NPM tokens to deposit for this epoch
Gauge[] distribution An array containing the distribution of emissions per block for each pool in this epoch

It will throw an error if:

  • The epoch number is 0 or not equal to the previous epoch number plus 1
  • The total emissions per block in the distribution is greater than the amount to deposit

function withdrawRewards(bytes32 key, uint256 amount) external#

This function allows an operator to withdraw the specified amount of rewards from the pool with the provided key. It can only be called by an operator.

Parameter Description
bytes32 key Enter the valid key of the liquidity gauge pool you wish to withdraw the rewards for.
uint256 amount The amount of rewards to withdraw

It will throw an error if:

  • The contract is paused
  • The caller is not a protocol member
  • The pool with the provided key does not exist

function deactivatePool(bytes32 key) external#

This function allows the contract owner to deactivate a pool with the provided key. It can only be called by the contract owner.

Parameter Description
bytes32 key Enter the valid key of the liquidity gauge pool you wish to deactivate before you can delete it.

It will throw an error if:

  • The contract is paused
  • The pool with the provided key does not exist
  • The pool with the provided key is already deactivated

function activatePool(bytes32 key) external#

This function allows the contract owner to activate a pool with the provided key. It can only be called by the contract owner.

Parameter Description
bytes32 key Enter the valid key of the liquidity gauge pool you deactivated earlier. Non-deactivated pools can not be activated.

It will throw an error if:

  • The contract is paused
  • The pool with the provided key does not exist
  • The pool with the provided key is already active

function deletePool(bytes32 key) external#

This function allows the contract owner to delete a pool with the provided key. It can only be called by the contract owner.

Parameter Description
bytes32 key Enter the valid key of the liquidity gauge pool you deactivated earlier. Non-deactivated pools can not be deleted.

It will throw an error if:

  • The contract is paused
  • The pool with the provided key does not exist
  • The pool with the provided key is active

function setOperator(address operator) external#

This function allows the contract owner to set the operator address. It can only be called by the contract owner.

Parameter Description
address operator Enter the address of the operator contracts that implements the `ILiquidityGaugePool` interface. The operator contracts are allowed to withdraw NPM token rewards on behalf of gauge pools.

It will throw an error if:

  • The contract is paused
  • The provided operator address is not already a protocol member

function isValid(bytes32 key) external view returns (bool)#

This function returns true if the pool with the provided key is valid, and false otherwise.

Parameter Description
bytes32 key Checks the given liquidity gauge pool key and returns true if it is found. Pools once active but deleted are not valid. Pools that are deactivated are still valid.

function isActive(bytes32 key) external view returns (bool)#

This function returns true if the pool with the provided key is active, and false otherwise.

Parameter Description
bytes32 key Checks the given liquidity gauge pool key and returns true if it found to be active. Pools that are deactivated can again be made active by using the `activatePool` function.

function get(bytes32 key) external view returns (PoolSetupArgs memory)#

This function returns the PoolSetupArgs struct for the pool with the provided key.

Parameter Description
bytes32 key Enter the liquidity gauge pool key for which the args will be returned. The pool setup args consists of parameters set during liquidity gauge pool creation or edits. 

function sumNpmDeposited() external view returns (uint256)#

This function returns the total amount of NPM tokens deposited across all epochs.

function sumNpmWithdrawn() external view returns (uint256)#

This function returns the total amount of NPM tokens withdrawn across all epochs.

function getLastEpoch() external view returns (uint256)#

This function returns the last epoch number for which a gauge was set.

function getAllocation(uint256 epoch) external view returns (uint256)#

This function returns the allocation of NPM tokens for the provided epoch number.

Parameter Description
uint256 epoch Provide the epoch number to obtain the combined total allocation for all gauge pools within that specific epoch.

function getEmissionPerBlock(bytes32 key) external view returns (uint256)#

This function returns the emission per block for the pool with the provided key.

Parameter Description
bytes32 key Enter the liquidity gauge pool key to get the last set NPM token emission per block value.

function recoverEther(address sendTo) external#

This function allows the contract owner to recover any Ether stuck in the contract. It can only be called by the contract owner.

Parameter Description
address sendTo Enter the address to send the recovered Ether to. Ensure that you provide a valid Ethereum address.

function recoverToken(IERC20Upgradeable malicious, address sendTo) external#

This function allows the contract owner to recover any ERC20 tokens stuck in the contract. It can only be called by the contract owner.

Parameter Description
IERC20Upgradeable malicious The ERC20 token contract address of the stuck tokens
address sendTo The address to send the recovered tokens to. Ensure that you provide a valid address.

function setPausers(address[] calldata accounts, bool[] calldata statuses) external#

This function allows the contract owner to set the pauser status of multiple accounts. It can only be called by the contract owner when the contract is not paused.

Parameter Description
address[] accounts An array containing the addresses for which to set the pauser status
bool[] statuses An array containing the pauser status for each address in the accounts array. A true value means the account will be a pauser, and a false value means the account will not be a pauser

It will throw an error if:

  • The contract is paused

Errors#

The contract may throw the following errors:

  1. AccessDeniedError: Thrown when the caller does not have the required access level (e.g., owner, operator, or pauser).
  2. BalanceInsufficientError: Thrown when the amount to deposit is less than the total required for gauge allocations.
  3. EmptyArgumentError: Thrown when an empty argument is provided to a function that requires a non-empty value.
  4. InvalidGaugeEpochError: Thrown when an invalid epoch is provided to the setGauge function.
  5. PoolAlreadyActiveError: Thrown when attempting to activate an already active pool.
  6. PoolAlreadyDeactivatedError: Thrown when attempting to deactivate an already deactivated pool.
  7. PoolAlreadyExistsError: Thrown when attempting to add a pool that already exists.
  8. PoolDeactivatedError: Thrown when attempting to edit a deactivated pool.
  9. PoolNotFoundError: Thrown when attempting to interact with a pool that does not exist.
  10. PoolNotActiveError: Thrown when attempting to set a gauge for an inactive pool.
  11. PoolNotDeactivatedError: Thrown when attempting to delete a pool that is not deactivated.
  12. ZeroAddressError: Thrown when a zero address is provided to a function that requires a non-zero address.

Events#

The contract emits the following events:

  1. GaugeAllocationTransferred: Emitted when a gauge allocation is transferred.
  2. GaugeControllerRegistryOperatorSet: Emitted when the operator is set.
  3. GaugeControllerRegistryPoolActivated: Emitted when a pool is activated.
  4. GaugeControllerRegistryPoolAddedOrEdited: Emitted when a pool is added or edited.
  5. GaugeControllerRegistryPoolDeactivated: Emitted when a pool is deactivated.
  6. GaugeControllerRegistryPoolDeleted: Emitted when a pool is deleted.
  7. GaugeControllerRegistryRewardsWithdrawn: Emitted when rewards are withdrawn.
  8. GaugeSet: Emitted when a gauge is set for a pool.

Modifiers#

The contract includes the following modifiers:

  1. onlyOperator: Restricts a function to be called only by the contract operator.
  2. whenNotPaused: Restricts a function to be called only when the contract is not paused.