Since the Nexus Mutual V2 protocol was launched in March 2023, the engineering team has identified several code bugs – none of which put any funds at risk – after extensive testing was conducted and areas for improvement based on members’ feedback since launch.
The engineering team has included enhancements to the smart contracts that would allow cover to be manually expired ahead of the expirations that happen within one 28-day capacity bucket. This would allow members to make cover available for expired covers on a product where demand is available to buy additional cover, as well as other smart contract enhancements outlined below.
The fixes and enhancements have been raised and approved through two Advisory Board (AB) on-chain votes.
The bugs and enhancements are outlined below and divided by contract. None of the bugs put user funds at risk; instead, they impacted members’ user experience when switching membership, managing a staking pool, or buying cover in certain scenarios, which are explained below.
With this enhancement, the user interface (UI) user experience is improved by allowing multiple function calls to be made at once.
The commission can be applied in 2 ways:
A) 100 * price% * ( 1 + comm rate)
B) 100 * price% / ( 1 - comm rate)
Before this upgrade, the commission was calculated using the A method above. With this enhancement, it has been changed to the B method above.
When users set commission rates they usually think they get x% of the cover fee–hence option B. The UI was handling this in the meantime by setting the commission percentage to match the results of the B formula.
When V2 first launched, cover expirations were grouped together in 28-day batches, for gas efficiency. If a cover expired during the 28-day period, that capacity didn’t become available until after the 28 days passed. Covers were expired in batches, but this prevented members from buying cover on in-demand products when capacity could have been manually expired.
This new feature allows for manual expiration, so covers can be expired and capacity can be opened up.
When the target price for existing cover products in a staking pool is updated, we need to calculate the current base price using the old target price and update the bumped price to that value.
[Bug] Fix how we calculate effective weights and force-recalculate them for all existing staking pools
The effective weight should be calculated based on raw capacity instead of weighted capacity. This bug could have led to misreporting of capacity in the pool, and at scale, this could have potentially prevented new cover buys from occurring.
In V2, new cover products can be created by a specific staking pool, which can only be underwritten by that staking pool. This bug fix introduced an extra check for managers adding cover products to their newly created staking pools, to make sure those products are allowed for that pool and non-deprecated.
The bug that was fixed presented the following problem:
Staking pool manager allocated stake to a product
Cover gets bought against that capacity
Someone delegating to that pool extends their original deposit
We don’t count the capacity already sold that their deposit was backing up, hence we could have double-sold capacity.
The bug fix makes sure that when a staker extends their deposit, we count the stake that is already allocated for an active cover, so we don’t double-allocate.
[Bug] Prevent switch / withdraw membership if users didn’t withdraw all tokens locked in V1 smart contracts
In V2, members can easily switch their membership address now that staking positions and covers are tokenized. However, some members have switched their membership address, while they still had NXM staked in the V1 smart contracts or staked in the V2 contracts for claims assessment or governance. This bug fix would prevent members from being able to switch their membership address or withdraw their membership without first removing their staked NXM from the V1 and/or V2 smart contracts.
The new swapOperator contract currently has a division issue, which impacts tight trades specific to the Enzyme v4 vault. This bug fix would resolve that issue.
The feature allows ETH to be rescued from the Capital Pool contract should any ETH balance ever get stuck in the SwapOperator.sol contract, as the result of a stuck CowSwap trade.
The full changes included in this upgrade can be found in release v2.1.0 in the smart contracts repo.
The following contracts were upgraded:
- Cover.sol (CO)
- StakingProducts.sol (SP)
- MemberRoles.sol (MR)