Giter Site home page Giter Site logo

protocol's Introduction

Neptune Mutual Cover

Protocol

Anyone who has NPM tokens can create a cover contract. To avoid spam, questionable, and confusing cover contracts, a creator has to burn 1000 NPM tokens. Additionally, the contract creator also needs to stake 4000 NPM tokens or more. The higher the sake, the more visibility the contract gets if there are multiple cover contracts with the same name or similar terms.

Read More

[comment]: #solidoc Start

Cover Contract (Cover.sol)

View Source: contracts/core/lifecycle/Cover.sol

โ†— Extends: CoverBase

Cover

The cover contract enables you to manage onchain covers.

Functions

Constructs this contract

function (IStore store) public nonpayable CoverBase 

Arguments

Name Type Description
store IStore Enter the store
Source Code
constructor(IStore store) CoverBase(store) {}

addCover

Adds a new coverage pool or cover contract. To add a new cover, you need to pay cover creation fee and stake minimum amount of NPM in the Vault.

Through the governance portal, projects will be able redeem the full cover fee at a later date.

Apply for Fee Redemption
https://docs.neptunemutual.com/covers/cover-fee-redemption

Read the documentation to learn more about the fees:
https://docs.neptunemutual.com/covers/contract-creators

function addCover(struct ICover.AddCoverArgs args) public nonpayable nonReentrant 
returns(address)

Arguments

Name Type Description
args struct ICover.AddCoverArgs
Source Code
function addCover(AddCoverArgs calldata args) public override nonReentrant returns (address) {
    s.mustNotBePaused();
    s.senderMustBeWhitelistedCoverCreator();

    require(args.stakeWithFee >= s.getUintByKey(ProtoUtilV1.NS_COVER_CREATION_MIN_STAKE), "Your stake is too low");

    s.addCoverInternal(args);

    emit CoverCreated(args.coverKey, args.info, args.tokenName, args.tokenSymbol, args.supportsProducts, args.requiresWhitelist);

    return s.deployVaultInternal(args.coverKey, args.tokenName, args.tokenSymbol);
  }

addCovers

function addCovers(struct ICover.AddCoverArgs[] args) external nonpayable
returns(vaults address[])

Arguments

Name Type Description
args struct ICover.AddCoverArgs[]
Source Code
function addCovers(AddCoverArgs[] calldata args) external override returns (address[] memory vaults) {
    vaults = new address[](args.length + 1);

    for (uint256 i = 0; i < args.length; i++) {
      vaults[i] = addCover(args[i]);
    }
  }

updateCover

Updates the cover contract. This feature is accessible only to the cover manager during withdrawal period.

function updateCover(bytes32 coverKey, string info) external nonpayable nonReentrant 

Arguments

Name Type Description
coverKey bytes32 Enter the cover key
info string IPFS hash. Check out the documentation for more info.
Source Code
function updateCover(bytes32 coverKey, string calldata info) external override nonReentrant {
    s.mustNotBePaused();
    s.mustEnsureAllProductsAreNormal(coverKey);
    AccessControlLibV1.mustBeCoverManager(s);
    s.mustBeDuringWithdrawalPeriod(coverKey);

    require(keccak256(bytes(s.getStringByKeys(ProtoUtilV1.NS_COVER_INFO, coverKey))) != keccak256(bytes(info)), "Duplicate content");

    s.updateCoverInternal(coverKey, info);
    emit CoverUpdated(coverKey, info);
  }

addProduct

Adds a product under a diversified cover pool

function addProduct(struct ICover.AddProductArgs args) public nonpayable nonReentrant 

Arguments

Name Type Description
args struct ICover.AddProductArgs
Source Code
function addProduct(AddProductArgs calldata args) public override nonReentrant {
    // @suppress-zero-value-check The uint values are validated in the function `addProductInternal`
    s.mustNotBePaused();
    s.senderMustBeWhitelistedCoverCreator();
    s.senderMustBeCoverOwnerOrAdmin(args.coverKey);

    s.addProductInternal(args);
    emit ProductCreated(args.coverKey, args.productKey, args.info);
  }

addProducts

function addProducts(struct ICover.AddProductArgs[] args) external nonpayable

Arguments

Name Type Description
args struct ICover.AddProductArgs[]
Source Code
function addProducts(AddProductArgs[] calldata args) external override {
    for (uint256 i = 0; i < args.length; i++) {
      addProduct(args[i]);
    }
  }

updateProduct

Updates a cover product. This feature is accessible only to the cover manager during withdrawal period.

function updateProduct(struct ICover.UpdateProductArgs args) external nonpayable nonReentrant 

Arguments

Name Type Description
args struct ICover.UpdateProductArgs
Source Code
function updateProduct(UpdateProductArgs calldata args) external override nonReentrant {
    // @suppress-zero-value-check The uint values are validated in the function `updateProductInternal`
    s.mustNotBePaused();
    s.mustBeSupportedProductOrEmpty(args.coverKey, args.productKey);
    AccessControlLibV1.mustBeCoverManager(s);
    s.mustBeDuringWithdrawalPeriod(args.coverKey);

    s.updateProductInternal(args);
    emit ProductUpdated(args.coverKey, args.productKey, args.info);
  }

disablePolicy

Allows disabling and enabling the purchase of policy for a product or cover. This function enables governance admin to disable or enable the purchase of policy for a product or cover. A cover contract when stopped restricts new policy purchases and frees up liquidity as policies expires.

  1. The policy purchases can be disabled and later enabled after current policies expire and liquidity is withdrawn.
  2. The policy purchases can be disabled temporarily to allow liquidity providers a chance to exit.
function disablePolicy(bytes32 coverKey, bytes32 productKey, bool status, string reason) external nonpayable nonReentrant 

Arguments

Name Type Description
coverKey bytes32 Enter the cover key you want to disable policy purchases
productKey bytes32 Enter the product key you want to disable policy purchases
status bool Set this to true if you disable or false to enable policy purchases
reason string Provide a reason to disable the policy purchases
Source Code
function disablePolicy(
    bytes32 coverKey,
    bytes32 productKey,
    bool status,
    string calldata reason
  ) external override nonReentrant {
    s.mustNotBePaused();
    AccessControlLibV1.mustBeCoverManager(s);
    s.mustBeSupportedProductOrEmpty(coverKey, productKey);

    require(status != s.isPolicyDisabledInternal(coverKey, productKey), status ? "Already disabled" : "Already enabled");

    s.disablePolicyInternal(coverKey, productKey, status);

    emit ProductStateUpdated(coverKey, productKey, msg.sender, status, reason);
  }

updateCoverCreatorWhitelist

Adds or removes an account to the cover creator whitelist. For the first version of the protocol, a cover creator has to be whitelisted before they can call the addCover function.

function updateCoverCreatorWhitelist(address[] accounts, bool[] statuses) external nonpayable nonReentrant 

Arguments

Name Type Description
accounts address[] Enter list of address of cover creators
statuses bool[] Set this to true if you want to add to or false to remove from the whitelist
Source Code
function updateCoverCreatorWhitelist(address[] calldata accounts, bool[] calldata statuses) external override nonReentrant {
    require(accounts.length > 0, "Please specify an account");
    require(accounts.length == statuses.length, "Invalid args");

    s.mustNotBePaused();
    AccessControlLibV1.mustBeCoverManager(s);

    for (uint256 i = 0; i < accounts.length; i++) {
      s.updateCoverCreatorWhitelistInternal(accounts[i], statuses[i]);
      emit CoverCreatorWhitelistUpdated(accounts[i], statuses[i]);
    }
  }

updateCoverUsersWhitelist

Adds or removes an account from the cover user whitelist. Whitelisting is an optional feature cover creators can enable. When a cover requires whitelist, you must add accounts to the cover user whitelist before they are able to purchase policies.

function updateCoverUsersWhitelist(bytes32 coverKey, bytes32 productKey, address[] accounts, bool[] statuses) external nonpayable nonReentrant 

Arguments

Name Type Description
coverKey bytes32 Enter cover key
productKey bytes32 Enter product key
accounts address[] Enter a list of accounts you would like to update the whitelist statuses of.
statuses bool[] Enter respective statuses of the specified whitelisted accounts.
Source Code
function updateCoverUsersWhitelist(
    bytes32 coverKey,
    bytes32 productKey,
    address[] calldata accounts,
    bool[] calldata statuses
  ) external override nonReentrant {
    s.mustNotBePaused();
    s.mustBeSupportedProductOrEmpty(coverKey, productKey);
    s.senderMustBeCoverOwnerOrAdmin(coverKey);

    s.updateCoverUsersWhitelistInternal(coverKey, productKey, accounts, statuses);
  }

checkIfWhitelistedCoverCreator

Signifies if the given account is a whitelisted cover creator

function checkIfWhitelistedCoverCreator(address account) external view
returns(bool)

Arguments

Name Type Description
account address
Source Code
function checkIfWhitelistedCoverCreator(address account) external view override returns (bool) {
    return s.getAddressBooleanByKey(ProtoUtilV1.NS_COVER_CREATOR_WHITELIST, account);
  }

checkIfWhitelistedUser

Signifies if the given account is a whitelisted user

function checkIfWhitelistedUser(bytes32 coverKey, bytes32 productKey, address account) external view
returns(bool)

Arguments

Name Type Description
coverKey bytes32
productKey bytes32
account address
Source Code
function checkIfWhitelistedUser(
    bytes32 coverKey,
    bytes32 productKey,
    address account
  ) external view override returns (bool) {
    return s.getAddressBooleanByKeys(ProtoUtilV1.NS_COVER_USER_WHITELIST, coverKey, productKey, account);
  }

Contracts

[comment]: #solidoc End

protocol's People

Contributors

binpmxstn avatar flashburst avatar rudolfnep avatar dependabot[bot] avatar omahs avatar clarinal12 avatar rupak-nm avatar naicky-neptune avatar sansiven avatar

Stargazers

 avatar David Leng avatar Stone Gao avatar mymoney avatar Matt Ma avatar hungngo avatar  avatar hunkar kaya avatar mariahenkenx40 avatar isocan avatar sakaleyn avatar  avatar  avatar Crypto Shadow avatar Hussaini Muhammad Auwal avatar  avatar  avatar  avatar  avatar srknssmn avatar Aleksandr Serdtsev avatar karyozeo avatar  avatar  avatar  avatar  avatar Herotodus avatar alex avatar  avatar Makhmut avatar Nurtileu avatar  avatar  avatar @nricox avatar Ani Jan avatar Dmytro avatar  avatar  avatar  avatar  avatar Ibnu Prawira avatar  avatar  avatar toprakdere avatar  avatar  avatar  avatar huynhdinh1994 avatar  avatar  avatar  avatar  avatar ilkeci avatar  avatar  avatar  avatar Kriptonec avatar  avatar  avatar Alwi Ghozali avatar  avatar  avatar  avatar DYLANFREE avatar  avatar  avatar bitcoin CEO avatar  avatar Pollock avatar  avatar  avatar sena avatar  avatar  avatar Y18j avatar arghani avatar AntonKlnd avatar Ramafadillah92 avatar Ulf avatar  avatar Emil Nazarov avatar Februari Situmorang avatar DarkNode avatar  avatar Rinto Pratama avatar  avatar  avatar  avatar alicomm avatar Freeguy avatar Bashir Fehintola avatar  avatar Majestique avatar  avatar Ilham Al Amin avatar humblepe0xple avatar  avatar  avatar  avatar Nifo avatar

Watchers

 avatar Oguz avatar Toni Hendra avatar Arie Ferdieansyah avatar Abdullah avatar  avatar  avatar  avatar  avatar Aminu Yusuff avatar  avatar Zi avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

protocol's Issues

[OZ] L-08 No unstaking window

Please note that OpenZeppelin reported this issue.

After an incident is resolved, successful stakers can retrieve their rewards provided the incident has not been finalized. When the incident occurred, they will have at least the claim period. However, if the incident was successfully disputed, there is no claim period and the incident can be finalized immediately before stakers have been provided sufficient time to claim their rewards. Consider including an unstaking window for this scenario.

[OZ] L-02 Collision between constants

Please note that OpenZeppelin reported this issue.

The NS_POOL_MAX_STAKE and NS_POOL_REWARD_TOKEN constants are defined to be the same string, which introduces the possibility of unexpected storage collisions. In the current code base they are used with non-overlapping data types, which are saved in different mappings. Nevertheless, in the interest of predictability, consider redefining the NS_POOL_MAX_STAKE constant to a unique string.

[OZ] N-11 Misleading comments

Please note that OpenZeppelin reported this issue.

Some comments are misleading, and the implementation does not follow the stated intention. For example,

  • In line 76, it was stated not to reset the first reporter by incident date. However, the first reporter is not saved by incident date, and it is deleted in line 90 of Finalization.sol . Similarly, the commented out lines do not contain the productKey and don't correspond to any saved value.
  • In line 128 of Protocol.sol , it is said that the protocol needs to be paused when the addMember function is invoked but in line 136, it ensures the protocol must not be paused.
  • The comments describing the callerMustBeX functions reference the "sender" rather than the caller parameter.
  • When initializing the protocol, the burner address must be non-zero but the comment says it isn't necessarily zero.

Consider updating the comments to be aligned with the code implementation

[OZ] L-11 Incorrect individual liquidity share

Please note that OpenZeppelin reported this issue.

The calculation of an individual's share of liquidity for a particular cover incorrectly uses values[5] instead of values[4] as the number of PODs. Since this is always zero, the returned share of liquidity will always be zero.

This has no implications within the current code base but would mislead external users that rely on it. Consider using the correct number of PODs in the calculation.

[OZ] H-02 Risk of insufficient liquidity

Please note that OpenZeppelin reported this issue.

When purchasing a cover, the protocol ensures it has enough funds to pay out all potential claimants. The computation of the existing commitments includes all covers expiring in the next 3 months, since this is the maximum policy duration. However, some covers may expire in the fourth month and these would be excluded from the calculation. Therefore, the protocol could sell more insurance than it can support, and some valid claimants may be unable to retrieve their payment.

Consider including the extra month in the commitment computation.

Protocol, NPM Token, and Oracle Dependency

Neptune Mutual Token (NPM) is planned to be launched months after the protocol is deployed (although this can change). Instead of NPM tokens, we will deploy a voucher. The voucher is a Proof of Authority Token (POT) distributed to a few select individuals and organisations who will participate in our governance portals.

Note that the POT holders are only concerned about the consensus and resolution process. Most, if not all, will not be a policyholder or liquidity provider. Also note that the community members will not receive or be able to acquire any POTs. Therefore, none of the protocol operations should be affected when the zero NPM is supplied. The features that allow setting the minimum (like minStakeToAddLiquidity, etc) should also allow zero values.

Task

Create a list of the affected functions. We can then refactor the codebase to satisfy this requirement.

Initial Requirement

  • Refactor RoutineInvoker's updateStateAndLiquidity to work even when IPriceOracle is not present.
  • Refactor features related to adding and removing liquidity, minimum NPM stake, etc in such a way that it works even when NPM tokens are not deployed

[OZ] L-03 Implicit timing assumptions

Please note that OpenZeppelin reported this issue.

To account for the coverage delay, some valid cxTokens may be excluded from making claims. Any coverage that will become active within 14 days but before the incident resolution will be disregarded. This implicitly assumes that no valid cover starts after either of these deadlines (otherwise it should also be excluded). Since the coverage delay and resolution window are configurable parameters, the assumptions may not hold. Consider calculating exclusions based on the specific parameters that are relevant to the incident being processed.

Error in `_withdrawFromDisabled` function

RoutineInvokerLibV1.sol
The function _withdrawFromDisabled allows to withdraw the amount lent to strategies which are currently disabled. Therefore strategy in strategy.withdraw(coverKey) is not active

function _withdrawFromDisabled(
  IStore s,
  bytes32 coverKey,
  address onBehalfOf
) private {
  address[] memory strategies = s.getDisabledStrategiesInternal();

  for (uint256 i = 0; i < strategies.length; i++) {
    ILendingStrategy strategy = ILendingStrategy(strategies[i]);
    uint256 balance = /* ... */

    if (balance > 0) {
      strategy.withdraw(coverKey);
    }
  }
}

But an exception is thrown because of the internal validations of vault contract

Error: VM Exception while processing transaction: reverted with reason string 'Not a strategy contract'
at ValidationLibV1.callerMustBeSpecificStrategyContract (contracts/libraries/ValidationLibV1.sol:148)
at VaultDelegate.preTransferToStrategy (contracts/core/delegates/VaultDelegateBase.sol:76)
at Vault.transferToStrategy (contracts/core/liquidity/VaultStrategy.sol:31)
at AaveStrategy.withdraw (contracts/core/liquidity/strategies/AaveStrategy.sol:149)
at RoutineInvokerLibV1._withdrawFromDisabled (contracts/libraries/RoutineInvokerLibV1.sol:263)
at RoutineInvokerLibV1._invokeAssetManagement (contracts/libraries/RoutineInvokerLibV1.sol:193)
at RoutineInvokerLibV1._invoke (contracts/libraries/RoutineInvokerLibV1.sol:46)
at RoutineInvokerLibV1.updateStateAndLiquidity (contracts/libraries/RoutineInvokerLibV1.sol:30)

The exact functions which are throwing this exception are callerMustBeStrategyContract and callerMustBeSpecificStrategyContract which only allow active strategies

  function callerMustBeStrategyContract(IStore s, address caller) external view {
    bool callerIsStrategyContract = s.getBoolByKey(_getIsActiveStrategyKey(caller));
    require(callerIsStrategyContract == true, "Not a strategy contract");
  }

  function callerMustBeSpecificStrategyContract(
    IStore s,
    address caller,
    bytes32 /*strategyName*/
  ) external view {
    bool callerIsStrategyContract = s.getBoolByKey(_getIsActiveStrategyKey(caller));
    require(callerIsStrategyContract == true, "Not a strategy contract");
  }

[OZ] M-01 Unenforced staking requirement

Please note that OpenZeppelin reported this issue.

Adding liquidity requires a liquidity provider to have at least a minimum amount of NPM tokens
staked in the vault.

However, the purpose and usefulness of this requirement is unclear, since it can be bypassed.
In particular:

  • there is no relationship between the amount of PODs created and the size of the stake
  • PODs are transferable to unstaked users, so users can provide liquidity without staking
  • staked users can exit their entire staked amount without redeeming any PODs by calling removeLiquidity with parameters podsToRedeem = 0 , npmStakeToRemove = amount, and exit = 1 ; the exit = 1 is crucial as it allows execution of line 234 of VaultLibV1.sol

Consider documenting and enforcing the intended relationship between NPM staking and
liquidity provision.

[OZ] N-01 transfer and send calls are no longer considered best practice

Please note that OpenZeppelin reported this issue.

When transfer or send calls are used to transfer Ether to an address, they forward only a limited amount of gas. This precludes destination addresses with complex fallback functions. Additionally, given that gas prices for EVM operations are sometimes repriced, code execution on the receiving end of these calls cannot be guaranteed in perpetuity.

There are multiple occurrences throughout the code base where transfer or send is used to transfer Ether. For instance:

Rather than using transfer or send, consider using address.call{value: amount}("") or the sendValue function of the OpenZeppelin Address library to transfer Ether.

[OZ] L-09 Protocol administrator needs to handle external tokens

Please note that OpenZeppelin reported this issue.

The protocol administrator is one of the most critical roles with immense privilege in the operation of the entire protocol. For example, only the administrator can re-initialize the protocol, grant key access control roles, as well as set up all staking and bonding pools.

However, when setting up a staking pool, a non-zero amount of reward tokens are required to be pre-transferred to the administrator account and pulled to the contract. This implies that the administrator needs to receive and approve the transaction a priori. This increases the attack surface and may not fit the intended security assumptions for a critical role.

Consider either using a less critical role to perform staking pool initialization or allowing pool initialization without any token transfer.

[OZ] N-18 Unnecessary complex code

Please note that OpenZeppelin reported this issue.

  • The s.getStablecoin() == address(token) == false expression on line 245 of StrategyLibV1.sol can be replaced with s.getStablecoin() != address(token).
  • Line 272 of CoverLibV1.sol casts the variable of type address to type address. The casting can be avoided.
  • isProtocolMember is defined both in line 257 of ProtoUtilV1.sol and line 85 of StoreBase.sol .

Please ignore the last point: isProtocolMember being defined in multiple places. The Store contract is standalone and can't depend on ProtoUtilV1. Neither can ProtoUtilV1 depend on Store.

[OZ] M-06 Unexpected deployer privileges

Please note that OpenZeppelin reported this issue.

The deployer address of the Store contract is recorded as a protocol member, which allows it to update the storage arbitrarily. The same address is set as the contract's owner role, which allows it to pause and unpause storage updates. We believe these are intended to be the same role, but they are not programmatically connected. In particular, if the owner address is renounced or transferred, the deployer will still be able to update storage.

Moreover, it is unclear why the Store owner or deployer requires the ability to modify storage arbitrarily.

Consider documenting the role in the Security overview if the role is required. Otherwise, consider renouncing protocol member privileges from the deployer address after the deployment is finished.

Decouple pause and unpause ACL logic in the store contract

Unlike the unpause feature, which is solely available to the owner, the pause feature of the store should be accessible to a separate account in order to programmatically pause the contract. In a hosted environment, this helps to avoid using the owner's private key.

Update function documentations

Below are the example of outdated and mistakes in the documentations

Screen Shot 2022-08-01 at 12 59 33 PM

  • The parameter amount is not included in the function documentation

Screen Shot 2022-08-01 at 12 58 11 PM

  • The parameter coverKey is duplicated

Missing documentation for the product status

The product status which is being used in addProduct, updateProduct and isActiveProductInternal functions is not documented properly anywhere except in comments of addProductInternal function

// Product Status
// 0 --> Deleted
// 1 --> Active
// 2 --> Retired
require(values[0] == 1, "Status must be active");

However, the name product status is confusing as it's already used to specify the resolution status of a product in the protocol

enum ProductStatus {
Normal,
Stopped,
IncidentHappened,
FalseReporting,
Claimable
}

addProduct

The first item of the last argument of addProduct function is documented as product status - values[0]. This parameter can be omitted as there is only one value accepted to execute the transaction successfully.

require(values[0] == 1, "Status must be active");

Question

Is there any need of having two different statuses for "Retired" and "Deleted" ? As they both offer almost same functionality as of now.

[OZ] L-01 Able to close non-empty staking pool

Please note that OpenZeppelin reported this issue.

A staking pool can be closed without checking if there is any remaining liquidity of either the staking token or the reward token. Once the pool is closed, neither deposit nor withdraw functions are allowed. Hence, users won't be able to access their funds. However a recovery agent is still able to retrieve both staking and reward tokens and distribute them as desired.

Consider checking for remaining liquidity before closing a pool

[OZ] M-02 Potential token transfer from unrelated account

Please note that OpenZeppelin reported this issue.

The CoverReassurance contract contains a mechanism to retrieve funds from an arbitrary account, as long as the account has provided a non-zero allowance. This would occur whenever a cover owner can front-run another cover owner's reassurance transaction, allowing them to redirect the funds to their own cover.

Even without front-running, there are multiple reasons an account may have a non-zero allowance, including:

  • Their addReassurance transaction failed and they didn't revoke the allowance.
  • They made an unlimited approval.
  • They approved a higher allowance than the amount they eventually transferred.

In all cases, an attacker can retrieve those funds and direct them towards a cover.

A recovery agent could still retrieve the funds from the CoverReassurance contract and distribute them as desired, although it is unclear how they would distinguish a front-running attack from one where a cover owner legitimately transfers funds from a different account.

Consider retrieving the tokens from the message sender rather than an arbitrary account parameter.

About updating cover rules

  • Cover creator changes to parameters and policy conditions should be Admin only
  • Feature to disable policy purchase temporarily

The Cover contract has incorrect ACL requirements.

A governance agent should not be concerned with:

  • updating cover creator whitelist
  • disabling policy purchase feature

I would suggest refactoring all instance of AccessControlLibV1.mustBeGovernanceAdmin(s) in the Cover.sol file to AccessControlLibV1.mustBeCoverManager(s)

A governance agent shouldn't worry about:

  • modifying the cover creator whitelist
  • disabling purchase policy feature

In the Cover.sol file, I would advise changing any occurrences of "AccessControlLibV1.mustBeGovernanceAdmin(s)" to "AccessControlLibV1.mustBeCoverManager(s)."

[OZ] M-05 Unable to unstake after finalization

Please note that OpenZeppelin reported this issue.

Reporters on the winning camp can unstake their tokens even after the incident has been finalized, albeit with no reward. However, the resolution deadline is not specific to a particular incident and is reset to 0 during finalization. Since the deadline is checked during unstaking, the operation will fail. This means that some successful NPM stakers will be unable to retrieve their funds.

In this scenario, a recovery agent could still retrieve the funds from the Resolution contract and distribute them as desired.

Consider recording the resolution deadline with the incident date so it does not need to be cleared during finalization.

[OZ] N-10 Incorrect array size

Please note that OpenZeppelin reported this issue.

The getCoverPoolSummaryInternal function creates an array of size 8 but only uses 7 positions. Similarly, the getInfoInternal function creates an array of size 11 but only uses 8 positions.

Consider resizing them accordingly.

[OZ] L-04 Imprecise bounds

There are several examples where the time windows or value ranges are defined inconsistently. In particular:

Add a Feature to "Close" a Report

Current Behavior

When an incident report is submitted, it undergoes a one-week reporting period and a one-week claim period.

Problem

Even if there is a monetary penalty, a motivated spammer (an attacker or a rival of a protected project) might still cause annoyance by submitting a phoney incident report. Thus, policy and liquidity transactions will be inaccessible for at least a week. Also troublesome is the occurrence of an actual incident before the conclusion of the reporting period.

Change Request

Add a function to immediately close (finalize) a report, rather than waiting a week, to avoid the submission of spam incident reports.

[OZ] H-01 Conflated staking pool reward balances

Please note that OpenZeppelin reported this issue.

Each staking pool specifies its own reward token and corresponding balance in the same aggregate contract. When retrieving this value, the token balance of the aggregate contract is returned. Since there could be multiple staking pools with the same reward token, this could include balances from other pools. It could also include any reward token balances that were directly sent to the contract.

Moreover, current user rewards could also be overstated, which would prevent users from claiming the last rewards. Since rewards are claimed when withdrawing stake, anyone could prevent users from unstaking by directly sending reward tokens to the staking pool contract. Any non-zero amount would be sufficient to trigger this scenario. If this occurs, a recovery agent could still retrieve the funds from the aggregate pool contract and distribute them as desired, although it is not clear how they should distribute the remaining rewards.

Consider reading the pool balance from the saved record.

[OZ] N-19 Unnecessary coupling

Please note that OpenZeppelin reported this issue.

When recording an attestation, the stake is recorded against the who address, but the reporter is set to the message sender. In both invocations, the who parameter is set to the message sender anyway. Nevertheless, in the interest of local reasoning, consider using the who address consistently. A similar observation applies to the first disputer.

Similarly, when calculating the future commitment, the number of months to check should depend on the global limit.

[OZ] L-06 Lack of input validation

Please note that OpenZeppelin reported this issue.

Consider including the corresponding validations.

Comments provides wrong Information

The comment and the code in the following file say two different things.

filename; ProtoUtilV1.sol
image

The comment should be Reverts if the caller is not one of the protocol member

[OZ] L-10 The info parameter might lose information about an IPFS hash

Please note that OpenZeppelin reported this issue.

The info parameter of the report, dispute, and other functions assume that the length of the IPFS hash is 32 bytes or shorter. However, that is not the case for CIDv1 where the hash can be longer than 32 bytes and also contain prefixes.

This leads to a data availability issue when NPM holders might be unable to retrieve the incident information from the smart contracts. Consequently, they are unable to decide whether to attest or refute the incident.

Consider using a different data structure for storing an IPFS hash.

[OZ] N-04 Copied in dependencies

Please note that OpenZeppelin reported this issue.

Dependencies in the lib directory, including openzeppelin-solidity, are copied in without any reference in .gitmodules. This makes it hard to keep track of the latest versions and easy to accidentally change the code inside.

Consider using forge install OpenZeppelin/openzeppelin-contracts for the latest version of the OpenZeppelin contracts.

The file .gitmodules is not checked into git because of .gitignore configuration. Without changing .gitignore, force push the .gitmodules file.

[OZ] M-04 Parallel access control

Please note that OpenZeppelin reported this issue.

The Protocol contract inherits the OpenZeppelin AccessControl contract, and uses it to define the role hierarchy. It also provides a mechanism for the administrator to grant an existing role to a new address. However, this mechanism functions in parallel to the inherited mechanism for granting roles. This leads to two inconsistencies:

  • A role administrator can bypass the whenNotPaused restriction by using the inherited
    mechanism.
  • The NS_ROLES_ADMIN can use the new mechanism to grant the NS_ROLES_GOVERNANCE_AGENT, even though they do not directly administer that role.

Consider ensuring consistency between the two mechanisms. Depending on the desired outcome, this could involve relying on the original mechanism, changing the role relationships, or overriding the inherited grantRole function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.