Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions contracts/interfaces/IStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,16 @@ interface IStakingPool is IERC721 {

function operatorTransfer(address from, address to, uint[] calldata tokenIds) external;

function updateTranches() external;
function updateTranches(bool updateUntilCurrentTimestamp) external;

function allocateStake(
CoverRequest calldata request
) external returns (uint allocatedAmount, uint premium, uint rewardsInNXM);

function deallocateStake(
uint productId,
uint start,
uint period,
uint amount,
uint premium,
uint globalRewardsRatio
CoverRequest memory request,
uint coverStartTime,
uint premium
) external;

function burnStake(uint productId, uint start, uint period, uint amount) external;
Expand Down
12 changes: 8 additions & 4 deletions contracts/libraries/Math.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ pragma solidity ^0.8.9;
*/
library Math {

function divRound(uint a, uint b) internal pure returns (uint) {
return (a + b / 2) / b;
}

function min(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
Expand All @@ -19,6 +15,14 @@ library Math {
return a > b ? a : b;
}

function divRound(uint a, uint b) internal pure returns (uint) {
return (a + b / 2) / b;
}

function divCeil(uint a, uint b) internal pure returns (uint) {
return (a + b - 1) / b;
}

// babylonian method
function sqrt(uint y) internal pure returns (uint) {

Expand Down
26 changes: 26 additions & 0 deletions contracts/libraries/UncheckedMath.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.9;

/**
* @dev Simple library that defines basic math functions that allow overflow
*/
library UncheckedMath {

function uncheckedAdd(uint a, uint b) internal pure returns (uint) {
unchecked { return a + b; }
}

function uncheckedSub(uint a, uint b) internal pure returns (uint) {
unchecked { return a - b; }
}

function uncheckedMul(uint a, uint b) internal pure returns (uint) {
unchecked { return a * b; }
}

function uncheckedDiv(uint a, uint b) internal pure returns (uint) {
unchecked { return a / b; }
}

}
11 changes: 4 additions & 7 deletions contracts/mocks/Cover/CoverMockStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,9 @@ contract CoverMockStakingPool is IStakingPool, ERC721 {
}

function deallocateStake(
uint /* productId */,
uint /* start */,
uint /* period */,
uint /* amount */,
uint /* premium */,
uint /* globalRewardsRatio */
CoverRequest memory /*request*/,
uint /*coverStartTime*/,
uint /*premium*/
) external {
}

Expand All @@ -121,7 +118,7 @@ contract CoverMockStakingPool is IStakingPool, ERC721 {
}
}

function updateTranches() external {
function updateTranches(bool) external {
totalSupply = totalSupply;
revert("CoverMockStakingPool: not callable");
}
Expand Down
108 changes: 67 additions & 41 deletions contracts/modules/cover/Cover.sol
Original file line number Diff line number Diff line change
Expand Up @@ -341,48 +341,17 @@ contract Cover is ICover, MasterAwareV2, IStakingPoolBeacon, ReentrancyGuard {
"Cover: payment asset deprecated"
);

uint refundInCoverAsset = 0;
uint refundInCoverAsset;

if (lastCoverSegment.start + lastCoverSegment.period > uint32(block.timestamp)) { // not expired
uint32 remainingPeriod = lastCoverSegment.start + lastCoverSegment.period - uint32(block.timestamp);

{
uint originalPoolAllocationsCount = coverSegmentAllocations[coverId][lastCoverSegmentIndex].length;

// Rollback previous cover
for (uint i = 0; i < originalPoolAllocationsCount; i++) {

PoolAllocation memory allocation = coverSegmentAllocations[coverId][lastCoverSegmentIndex][i];

stakingPool(allocation.poolId).deallocateStake(
cover.productId,
lastCoverSegment.start,
lastCoverSegment.period,
allocation.coverAmountInNXM,
allocation.premiumInNXM,
lastCoverSegment.globalRewardsRatio
);

coverSegmentAllocations[coverId][lastCoverSegmentIndex][i].premiumInNXM
*= (lastCoverSegment.period - remainingPeriod) / lastCoverSegment.period;

// Compute NXM rewards to be rolled back
uint deallocatedRewardsInNXM = allocation.premiumInNXM
* remainingPeriod / lastCoverSegment.period
* lastCoverSegment.globalRewardsRatio / REWARD_DENOMINATOR;

tokenController().burnStakingPoolNXMRewards(deallocatedRewardsInNXM, allocation.poolId);
}
}

refundInCoverAsset = lastCoverSegment.priceRatio
* lastCoverSegment.amount
/ PRICE_DENOMINATOR
* remainingPeriod
/ MAX_COVER_PERIOD;

// Edit the last cover segment so it ends at the current block
lastCoverSegment.period = lastCoverSegment.period - remainingPeriod;
// if the last segment is not expired
if (lastCoverSegment.start + lastCoverSegment.period > uint32(block.timestamp)) {
refundInCoverAsset = deallocateCapacity(
coverId,
lastCoverSegmentIndex,
product,
cover,
lastCoverSegment
);
}

(uint totalPremiumInNXM, uint totalCoveredAmountInPayoutAsset) = _buyCover(buyCoverParams, coverId, poolAllocations);
Expand All @@ -398,6 +367,63 @@ contract Cover is ICover, MasterAwareV2, IStakingPoolBeacon, ReentrancyGuard {
emit CoverEdited(coverId, cover.productId, lastCoverSegmentIndex + 1, msg.sender);
}

function deallocateCapacity(
uint coverId,
uint lastCoverSegmentIndex,
Product memory product,
CoverData memory cover,
CoverSegment memory lastCoverSegment
) internal returns (uint refundInCoverAsset) {

uint32 remainingPeriod = lastCoverSegment.start + lastCoverSegment.period - uint32(block.timestamp);
{
uint originalPoolAllocationsCount = coverSegmentAllocations[coverId][lastCoverSegmentIndex].length;

// Rollback previous cover
for (uint i = 0; i < originalPoolAllocationsCount; i++) {

PoolAllocation memory allocation = coverSegmentAllocations[coverId][lastCoverSegmentIndex][i];
CoverRequest memory request = CoverRequest(
coverId,
cover.productId,
allocation.coverAmountInNXM,
lastCoverSegment.period,
_productTypes[product.productType].gracePeriodInDays * 1 days,
// TODO globalCapacityRatio and capacityReductionRatio need to be stored at cover buy
globalCapacityRatio,
product.capacityReductionRatio,
lastCoverSegment.globalRewardsRatio
);

stakingPool(allocation.poolId).deallocateStake(
request,
lastCoverSegment.start,
allocation.premiumInNXM
);

coverSegmentAllocations[coverId][lastCoverSegmentIndex][i].premiumInNXM
*= (lastCoverSegment.period - remainingPeriod) / lastCoverSegment.period;

// Compute NXM rewards to be rolled back
uint deallocatedRewardsInNXM = allocation.premiumInNXM
* remainingPeriod / lastCoverSegment.period
* lastCoverSegment.globalRewardsRatio / REWARD_DENOMINATOR;

tokenController().burnStakingPoolNXMRewards(deallocatedRewardsInNXM, allocation.poolId);
}
}

refundInCoverAsset = lastCoverSegment.priceRatio
* lastCoverSegment.amount
/ PRICE_DENOMINATOR
* remainingPeriod
/ MAX_COVER_PERIOD;

// TODO: write to storage instead of memory
// Edit the last cover segment so it ends at the current block
lastCoverSegment.period = lastCoverSegment.period - remainingPeriod;
}

function handlePaymentAndRefund(
BuyCoverParams memory buyCoverParams,
uint totalPremiumInNXM,
Expand Down
Loading