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
7 changes: 7 additions & 0 deletions contracts/interfaces/ICover.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ interface ICover {

function globalCapacityRatio() external view returns (uint24);

function getPriceAndCapacityRatios(uint[] calldata productIds) external view returns (
uint _globalCapacityRatio,
uint _globalMinPriceRatio,
uint[] memory _initialPriceRatios,
uint[] memory _capacityReductionRatios
);

/* === MUTATIVE FUNCTIONS ==== */

function migrateCovers(uint[] calldata coverIds, address newOwner) external returns (uint[] memory newCoverIds);
Expand Down
21 changes: 9 additions & 12 deletions contracts/interfaces/IStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ struct DepositRequest {

struct ProductParams {
uint productId;
bool setWeight;
uint targetWeight;
bool setPrice;
uint targetPrice;
bool recalculateEffectiveWeight;
bool setTargetWeight;
uint8 targetWeight;
bool setTargetPrice;
uint96 targetPrice;
}

struct ProductInitializationParams {
Expand Down Expand Up @@ -71,8 +72,8 @@ interface IStakingPool {
uint rewardsShares;
}

struct Product {
uint8 lastWeight;
struct StakedProduct {
uint8 lastEffectiveWeight;
uint8 targetWeight;
uint96 targetPrice;
uint96 nextPrice;
Expand Down Expand Up @@ -115,16 +116,12 @@ interface IStakingPool {
WithdrawRequest[] memory params
) external returns (uint stakeToWithdraw, uint rewardsToWithdraw);

function addProducts(ProductParams[] memory params) external;

function removeProducts(uint[] memory productIds) external;

function setProductDetails(ProductParams[] memory params) external;

function setPoolFee(uint newFee) external;

function setPoolPrivacy(bool isPrivatePool) external;

function setProducts(ProductParams[] memory params) external;

function manager() external view returns (address);

function getActiveStake() external view returns (uint);
Expand Down
13 changes: 10 additions & 3 deletions contracts/mocks/Cover/CoverMockStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

pragma solidity ^0.8.16;

import "../Tokens/ERC721Mock.sol";
import "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-v4/utils/Strings.sol";
import "../../interfaces/IStakingPool.sol";
import "../../modules/staking/StakingPool.sol";
import "../Tokens/ERC721Mock.sol";


contract CoverMockStakingPool is IStakingPool, ERC721Mock {
Expand All @@ -22,12 +23,13 @@ contract CoverMockStakingPool is IStakingPool, ERC721Mock {

mapping (uint => uint) public usedCapacity;
mapping (uint => uint) public stakedAmount;
// product id => Product
mapping(uint => Product) public products;
// product id => StakedProduct
mapping(uint => StakedProduct) public products;
mapping (uint => uint) public mockPrices;

uint public constant MAX_PRICE_RATIO = 10_000;
uint constant REWARDS_DENOMINATOR = 10_000;
uint public constant GLOBAL_MIN_PRICE_RATIO = 100; // 1%

uint public poolId;
// erc721 supply
Expand Down Expand Up @@ -92,6 +94,11 @@ contract CoverMockStakingPool is IStakingPool, ERC721Mock {
) external {
}

function setProducts(ProductParams[] memory params) external {
totalSupply = totalSupply;
params;
}

function calculatePremium(uint priceRatio, uint coverAmount, uint period) public pure returns (uint) {
return priceRatio * coverAmount / MAX_PRICE_RATIO * period / 365 days;
}
Expand Down
88 changes: 88 additions & 0 deletions contracts/mocks/StakingPool/SPMockCoverProducts.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.0;

import "../../interfaces/IStakingPool.sol";
import "../../interfaces/ICover.sol";
import "../../modules/cover/CoverUtilsLib.sol";

contract SPMockCoverProducts {
uint24 public constant globalCapacityRatio = 2;
uint256 public constant globalRewardsRatio = 1;

uint public constant GLOBAL_MIN_PRICE_RATIO = 100; // 1%

mapping(uint => address) public stakingPool;
mapping(uint256 => Product) public products;
mapping(uint256 => ProductType) public productTypes;

function setStakingPool(address addr, uint id) public {
stakingPool[id] = addr;
}

function setProduct(Product memory product, uint256 id) public {
products[id] = product;
}

function setProductType(ProductType calldata product, uint256 id) public {
productTypes[id] = product;
}


function getPriceAndCapacityRatios(uint[] calldata productIds) public view returns (
uint _globalCapacityRatio,
uint _globalMinPriceRatio,
uint[] memory _initialPrices,
uint[] memory _capacityReductionRatios
) {
_globalCapacityRatio = uint(globalCapacityRatio);
_globalMinPriceRatio = GLOBAL_MIN_PRICE_RATIO;
_capacityReductionRatios = new uint[](productIds.length);
_initialPrices = new uint[](productIds.length);
for (uint i = 0; i < productIds.length; i++) {
Product memory product = products[productIds[i]];
require(product.initialPriceRatio > 0, "Cover: Product deprecated or not initialized");
_initialPrices[i] = uint(product.initialPriceRatio);
_capacityReductionRatios[i] = uint(product.capacityReductionRatio);
}
}

function allocateCapacity(
BuyCoverParams memory params,
uint256 coverId,
IStakingPool _stakingPool
) public returns (uint256 coveredAmountInNXM, uint256 premiumInNXM, uint256 rewardsInNXM) {
Product memory product = products[params.productId];
uint256 gracePeriod = uint256(productTypes[product.productType].gracePeriodInDays) * 1 days;

return _stakingPool.allocateStake(
CoverRequest(
coverId,
params.productId,
params.amount,
params.period,
gracePeriod,
globalCapacityRatio,
product.capacityReductionRatio,
globalRewardsRatio
)
);
}

function initializeStaking(
address staking_,
address _manager,
bool _isPrivatePool,
uint256 _initialPoolFee,
uint256 _maxPoolFee,
ProductInitializationParams[] memory params,
uint256 _poolId
) external {

for (uint i = 0; i < params.length; i++) {
params[i].initialPrice = products[params[i].productId].initialPriceRatio;
require(params[i].targetPrice >= GLOBAL_MIN_PRICE_RATIO, "CoverUtilsLib: Target price below GLOBAL_MIN_PRICE_RATIO");
}
IStakingPool(staking_).initialize(_manager, _isPrivatePool, _initialPoolFee, _maxPoolFee, params, _poolId);
}
}
19 changes: 19 additions & 0 deletions contracts/mocks/TokenControllerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ pragma solidity ^0.5.0;
import "../abstract/MasterAware.sol";
import "../modules/token/NXMToken.sol";

interface ICover {
function stakingPool(uint poolId) external view returns (address);
}

contract TokenControllerMock is MasterAware {

struct StakingPoolNXMBalances {
uint128 rewards;
uint128 deposits;
}


NXMToken public token;
ICover public cover;
address public addToWhitelistLastCalledWtih;
address public removeFromWhitelistLastCalledWtih;

Expand All @@ -36,6 +42,7 @@ contract TokenControllerMock is MasterAware {

function changeDependentContractAddress() public {
token = NXMToken(master.tokenAddress());
cover = ICover(master.getLatestAddress("CO"));
}

function operatorTransfer(address _from, address _to, uint _value) onlyInternal external returns (bool) {
Expand All @@ -58,6 +65,18 @@ contract TokenControllerMock is MasterAware {
stakingPoolNXMBalances[poolId].rewards -= uint128(amount);
}

function setContractAddresses(address coverAddr, address tokenAddr) public {
cover = ICover(coverAddr);
token = NXMToken(tokenAddr);
}

function depositStakedNXM(address from, uint amount, uint poolId) external {
require(msg.sender == address(cover.stakingPool(poolId)), "TokenController: msg.sender not staking pool");

stakingPoolNXMBalances[poolId].deposits += uint128(amount);
token.operatorTransfer(from, amount);
}

/* unused functions */

modifier unused {
Expand Down
24 changes: 22 additions & 2 deletions contracts/modules/cover/Cover.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract Cover is ICover, MasterAwareV2, IStakingPoolBeacon, ReentrancyGuard {

uint private constant MAX_COMMISSION_RATIO = 2500; // 25%

uint private constant GLOBAL_MIN_PRICE_RATIO = 100; // 1%
uint public constant GLOBAL_MIN_PRICE_RATIO = 100; // 1%

uint private constant ONE_NXM = 1e18;

Expand Down Expand Up @@ -550,7 +550,8 @@ contract Cover is ICover, MasterAwareV2, IStakingPoolBeacon, ReentrancyGuard {
manager,
isPrivatePool,
initialPoolFee,
maxPoolFee
maxPoolFee,
GLOBAL_MIN_PRICE_RATIO
);

address stakingPoolAddress = CoverUtilsLib.createStakingPool(
Expand Down Expand Up @@ -787,6 +788,25 @@ contract Cover is ICover, MasterAwareV2, IStakingPoolBeacon, ReentrancyGuard {
return (1 << coverAsset) & assetsBitMap > 0;
}

function getPriceAndCapacityRatios(uint[] calldata productIds) public view returns (
uint _globalCapacityRatio,
uint _globalMinPriceRatio,
uint[] memory _initialPrices,
uint[] memory _capacityReductionRatios
) {
_globalMinPriceRatio = GLOBAL_MIN_PRICE_RATIO;
_globalCapacityRatio = uint(globalCapacityRatio);
_capacityReductionRatios = new uint[](productIds.length);
_initialPrices = new uint[](productIds.length);

for (uint i = 0; i < productIds.length; i++) {
Product memory product = _products[productIds[i]];
require(product.initialPriceRatio > 0, "Cover: Product deprecated or not initialized");
_initialPrices[i] = uint(product.initialPriceRatio);
_capacityReductionRatios[i] = uint(product.capacityReductionRatio);
}
}

function _isCoverAssetDeprecated(
uint32 deprecatedCoverAssetsBitmap,
uint8 assetId
Expand Down
4 changes: 3 additions & 1 deletion contracts/modules/cover/CoverUtilsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ library CoverUtilsLib {
bool isPrivatePool;
uint initialPoolFee;
uint maxPoolFee;
uint globalMinPriceRatio;
}

function migrateCoverFromOwner(
Expand Down Expand Up @@ -137,7 +138,8 @@ library CoverUtilsLib {

// override with initial price
for (uint i = 0; i < productInitParams.length; i++) {
productInitParams[0].initialPrice = products[productInitParams[i].productId].initialPriceRatio;
productInitParams[i].initialPrice = products[productInitParams[i].productId].initialPriceRatio;
require(productInitParams[i].targetPrice >= poolInitParams.globalMinPriceRatio, "CoverUtilsLib: Target price below GLOBAL_MIN_PRICE_RATIO");
}
}

Expand Down
Loading