Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 4 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 16439653 | 1133 days ago | Contract Creation | 0 ETH | |||
| 0x60806040 | 16239171 | 1161 days ago | Contract Creation | 0 ETH | |||
| 0x60806040 | 16087878 | 1182 days ago | Contract Creation | 0 ETH | |||
| 0x60806040 | 15912007 | 1207 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
VaultFactory
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../../interfaces/IVault.sol";
import "../../interfaces/IVaultFactory.sol";
import "../../libraries/VaultFactoryLibV1.sol";
import "../Recoverable.sol";
/**
* @title Vault Factory Contract
*
* @dev When a new cover is created, an associated liquidity pool or vault is also created.
* The cover contract deploys new vaults on demand by utilizing the vault factory contract.
*
*/
contract VaultFactory is IVaultFactory, Recoverable {
using ProtoUtilV1 for IStore;
using ValidationLibV1 for IStore;
/**
* @dev Constructs this contract
* @param store Provide the store contract instance
*/
constructor(IStore store) Recoverable(store) {} // solhint-disable-line
/**
* @dev Deploys a new instance of Vault
*
* @custom:suppress-acl This function is only accessible to the cover contract
*
* @param coverKey Enter the cover key related to this Vault instance
*/
function deploy(
bytes32 coverKey,
string calldata tokenName,
string calldata tokenSymbol
) external override nonReentrant returns (address addr) {
s.mustNotBePaused();
s.senderMustBeCoverContract();
(bytes memory bytecode, bytes32 salt) = VaultFactoryLibV1.getByteCodeInternal(s, coverKey, tokenName, tokenSymbol, s.getStablecoinAddressInternal());
// solhint-disable-next-line
assembly {
addr := create2(
callvalue(), // wei sent with current call
// Actual code starts after skipping the first 32 bytes
add(bytecode, 0x20),
mload(bytecode), // Load the size of code contained in the first 32 bytes
salt // Salt from function arguments
)
if iszero(extcodesize(addr)) {
// @suppress-revert This is correct usage
revert(0, 0)
}
}
emit VaultDeployed(addr, coverKey, tokenName, tokenSymbol);
}
/**
* @dev Version number of this contract
*/
function version() external pure override returns (bytes32) {
return "v0.1";
}
/**
* @dev Name of this contract
*/
function getName() external pure override returns (bytes32) {
return ProtoUtilV1.CNAME_VAULT_FACTORY;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface IVault is IMember, IERC20 {
struct VaultInfoType {
uint256 totalPods;
uint256 balance;
uint256 extendedBalance;
uint256 totalReassurance;
uint256 myPodBalance;
uint256 myShare;
uint256 withdrawalOpen;
uint256 withdrawalClose;
}
struct AddLiquidityArgs {
/// @dev Enter the cover key
bytes32 coverKey;
/// @dev Enter the amount of liquidity token to supply.
uint256 amount;
/// @dev Enter the amount of NPM token to stake. Will be locked for a minimum window of one withdrawal period.
uint256 npmStakeToAdd;
/// @dev Enter referral code
bytes32 referralCode;
}
event GovernanceTransfer(address indexed to, uint256 amount);
event StrategyTransfer(address indexed token, address indexed strategy, bytes32 indexed name, uint256 amount);
event StrategyReceipt(address indexed token, address indexed strategy, bytes32 indexed name, uint256 amount, uint256 income, uint256 loss);
event PodsIssued(address indexed account, uint256 issued, uint256 liquidityAdded, bytes32 indexed referralCode);
event PodsRedeemed(address indexed account, uint256 redeemed, uint256 liquidityReleased);
event FlashLoanBorrowed(address indexed lender, address indexed borrower, address indexed stablecoin, uint256 amount, uint256 fee);
event NpmStaken(address indexed account, uint256 amount);
event NpmUnstaken(address indexed account, uint256 amount);
event InterestAccrued(bytes32 indexed coverKey);
event Entered(bytes32 indexed coverKey, address indexed account);
event Exited(bytes32 indexed coverKey, address indexed account);
function key() external view returns (bytes32);
function sc() external view returns (address);
/**
* @dev Adds liquidity to the specified cover contract
*/
function addLiquidity(AddLiquidityArgs calldata args) external;
function accrueInterest() external;
/**
* @dev Removes liquidity from the specified cover contract
* @param coverKey Enter the cover key
* @param amount Enter the amount of liquidity token to remove.
* @param npmStake Enter the amount of NPM stake to remove.
* @param exit Indicates NPM stake exit.
*/
function removeLiquidity(
bytes32 coverKey,
uint256 amount,
uint256 npmStake,
bool exit
) external;
/**
* @dev Transfers liquidity to governance contract.
* @param coverKey Enter the cover key
* @param to Enter the destination account
* @param amount Enter the amount of liquidity token to transfer.
*/
function transferGovernance(
bytes32 coverKey,
address to,
uint256 amount
) external;
/**
* @dev Transfers liquidity to strategy contract.
* @param coverKey Enter the cover key
* @param strategyName Enter the strategy's name
* @param amount Enter the amount of liquidity token to transfer.
*/
function transferToStrategy(
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external;
/**
* @dev Receives from strategy contract.
* @param coverKey Enter the cover key
* @param strategyName Enter the strategy's name
* @param amount Enter the amount of liquidity token to transfer.
*/
function receiveFromStrategy(
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external;
function calculatePods(uint256 forStablecoinUnits) external view returns (uint256);
function calculateLiquidity(uint256 podsToBurn) external view returns (uint256);
function getInfo(address forAccount) external view returns (VaultInfoType memory info);
/**
* @dev Returns the stablecoin balance of this vault
* This also includes amounts lent out in lending strategies
*/
function getStablecoinBalanceOf() external view returns (uint256);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IStore.sol";
import "./IMember.sol";
interface IVaultFactory is IMember {
event VaultDeployed(address vault, bytes32 indexed coverKey, string name, string symbol);
function deploy(
bytes32 coverKey,
string calldata name,
string calldata symbol
) external returns (address);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../core/liquidity/Vault.sol";
library VaultFactoryLibV1 {
/**
* @dev Gets the bytecode of the `Vault` contract
* @param s Provide the store instance
* @param coverKey Provide the cover key
* @param stablecoin Specify the liquidity token for this Vault
*/
function getByteCodeInternal(
IStore s,
bytes32 coverKey,
string calldata tokenName,
string calldata tokenSymbol,
address stablecoin
) external pure returns (bytes memory bytecode, bytes32 salt) {
salt = keccak256(abi.encodePacked(ProtoUtilV1.NS_CONTRACTS, ProtoUtilV1.CNS_COVER_VAULT, coverKey));
//slither-disable-next-line too-many-digits
bytecode = abi.encodePacked(type(Vault).creationCode, abi.encode(s, coverKey, tokenName, tokenSymbol, stablecoin));
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/security/ReentrancyGuard.sol";
import "../interfaces/IRecoverable.sol";
import "../libraries/BaseLibV1.sol";
import "../libraries/ValidationLibV1.sol";
/**
*
* @title Recoverable Contract
* @dev The recoverable contract enables "Recovery Agents" to recover
* Ether and ERC-20 tokens sent to this address.
*
* To learn more about our recovery policy, please refer to the following doc:
* https://docs.neptunemutual.com/usage/recovering-cryptocurrencies
*
*/
abstract contract Recoverable is ReentrancyGuard, IRecoverable {
using ValidationLibV1 for IStore;
IStore public override s;
constructor(IStore store) {
require(address(store) != address(0), "Invalid Store");
s = store;
}
/**
* @dev Recover all Ether held by the contract.
* On success, no event is emitted because the recovery feature does
* not have any significance in the SDK or the UI.
*/
function recoverEther(address sendTo) external override nonReentrant {
s.mustNotBePaused();
AccessControlLibV1.mustBeRecoveryAgent(s);
BaseLibV1.recoverEtherInternal(sendTo);
}
/**
* @dev Recover all ERC-20 compatible tokens sent to this address.
* On success, no event is emitted because the recovery feature does
* not have any significance in the SDK or the UI.
*
* @custom:suppress-malicious-erc The malicious ERC-20 `token` should only be invoked via `NTransferUtil`.
* @custom:suppress-address-trust-issue Although the token can't be trusted, the recovery agent has to check the token code manually.
*
* @param token ERC-20 The address of the token contract
*/
function recoverToken(address token, address sendTo) external override nonReentrant {
s.mustNotBePaused();
AccessControlLibV1.mustBeRecoveryAgent(s);
BaseLibV1.recoverTokenInternal(token, sendTo);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IMember {
/**
* @dev Version number of this contract
*/
function version() external pure returns (bytes32);
/**
* @dev Name of this contract
*/
function getName() external pure returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IStore {
event PausersSet(address indexed addedBy, address[] accounts, bool[] statuses);
function setPausers(address[] calldata accounts, bool[] calldata statuses) external;
function setAddress(bytes32 k, address v) external;
function setAddressBoolean(
bytes32 k,
address a,
bool v
) external;
function setUint(bytes32 k, uint256 v) external;
function addUint(bytes32 k, uint256 v) external;
function subtractUint(bytes32 k, uint256 v) external;
function setUints(bytes32 k, uint256[] calldata v) external;
function setString(bytes32 k, string calldata v) external;
function setBytes(bytes32 k, bytes calldata v) external;
function setBool(bytes32 k, bool v) external;
function setInt(bytes32 k, int256 v) external;
function setBytes32(bytes32 k, bytes32 v) external;
function setAddressArrayItem(bytes32 k, address v) external;
function setBytes32ArrayItem(bytes32 k, bytes32 v) external;
function deleteAddress(bytes32 k) external;
function deleteUint(bytes32 k) external;
function deleteUints(bytes32 k) external;
function deleteString(bytes32 k) external;
function deleteBytes(bytes32 k) external;
function deleteBool(bytes32 k) external;
function deleteInt(bytes32 k) external;
function deleteBytes32(bytes32 k) external;
function deleteAddressArrayItem(bytes32 k, address v) external;
function deleteBytes32ArrayItem(bytes32 k, bytes32 v) external;
function deleteAddressArrayItemByIndex(bytes32 k, uint256 i) external;
function deleteBytes32ArrayItemByIndex(bytes32 k, uint256 i) external;
function getAddressValues(bytes32[] calldata keys) external view returns (address[] memory values);
function getAddress(bytes32 k) external view returns (address);
function getAddressBoolean(bytes32 k, address a) external view returns (bool);
function getUintValues(bytes32[] calldata keys) external view returns (uint256[] memory values);
function getUint(bytes32 k) external view returns (uint256);
function getUints(bytes32 k) external view returns (uint256[] memory);
function getString(bytes32 k) external view returns (string memory);
function getBytes(bytes32 k) external view returns (bytes memory);
function getBool(bytes32 k) external view returns (bool);
function getInt(bytes32 k) external view returns (int256);
function getBytes32(bytes32 k) external view returns (bytes32);
function countAddressArrayItems(bytes32 k) external view returns (uint256);
function countBytes32ArrayItems(bytes32 k) external view returns (uint256);
function getAddressArray(bytes32 k) external view returns (address[] memory);
function getBytes32Array(bytes32 k) external view returns (bytes32[] memory);
function getAddressArrayItemPosition(bytes32 k, address toFind) external view returns (uint256);
function getBytes32ArrayItemPosition(bytes32 k, bytes32 toFind) external view returns (uint256);
function getAddressArrayItemByIndex(bytes32 k, uint256 i) external view returns (address);
function getBytes32ArrayItemByIndex(bytes32 k, uint256 i) external view returns (bytes32);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/interfaces/IERC3156FlashLender.sol";
import "./WithFlashLoan.sol";
pragma solidity ^0.8.0;
/**
* @title Vault Contract
*
* @dev When a cover is created, a corresponding liquidity pool is also constituted.
* An instance of this contract represents the liquidity pool of a cover.
* The vaults are denominated in a single stablecoin and may be less susceptible
* to underwriting risks associated with cryptocurrency price volatility.
*
* <br /> <br />
*
* When requested by the Cover Contract, the VaultFactory contract deploys a vault.
* Per cover, only one vault is permitted. Since the vault contract is not upgradable,
* some of the validation logic of it is outsourced to the VaultDelegate contract.
*
* <br /> <br />
*
* The vault contract is also an ERC-20 token, commonly known as POD (or Proof of Deposit).
* As there is always on-chain stablecoin liquidity available for withdrawal,
* PODs are fully redeemable and also income or loss bearing certificates
* (loss if the cover had an event that resulted in a claims payout).
*
* Unlike [cxTokens](cxToken.md), PODs can be freely transferred, staked,
* and exchanged on secondary marketplaces.
*
* <br /> <br />
*
* **Disclaimer:**
* <br /> <br />
*
* **The protocol does not provide any warranty, guarantee, or endorsement
* for the peg of this stablecoin or any other stablecoin we may use on a different chain.**
*
* <br /> <br />
*
* Both risk poolers (underwriters) and policyholders
* must agree to utilize the same stablecoin to interfact with the protocol.
*
* Note that the Neptune Mutual protocol only covers risks related to smart contracts and,
* to a certain extent, frontend attacks. We don't cover risks arising from
* teams losing private keys because of gross misconduct or negligence.
* We don't cover people who put their money at risk in trading activities
* like margin calls, leverage trading, or liquidation.
* We don't cover 51% attack or any other type of consensus attack.
* We don't cover bridge hacks and a [whole variety of other exclusions](https://docs.neptunemutual.com/usage/standard-exclusions).
*
*/
contract Vault is WithFlashLoan {
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
/**
* @dev Constructs this contract
*
* @param store Provide store instance
* @param coverKey Provide a cover key that doesn't have a vault deployed
* @param tokenName Enter the token name of the POD. Example: `Uniswap nDAI` or `Uniswap nUSDC`
* @param tokenSymbol Enter the token symbol of the POD. Example: UNI-NDAI or `UNI-NUSDC`.
* @param stablecoin Provide an instance of the stablecoin this vault supports.
*
*/
constructor(
IStore store,
bytes32 coverKey,
string memory tokenName,
string memory tokenSymbol,
IERC20 stablecoin
) VaultBase(store, coverKey, tokenName, tokenSymbol, stablecoin) {} // solhint-disable-line
/**
* @dev Gets information of a given vault by the cover key
*
* Warning: this function does not validate the input argument.
*
* @param you The address for which the info will be customized
*
*/
function getInfo(address you) external view override returns (VaultInfoType memory) {
return delegate().getInfoImplementation(key, you);
}
/**
* @dev Version number of this contract
*/
function version() external pure override returns (bytes32) {
return "v0.1";
}
/**
* @dev Name of this contract
*/
function getName() external pure override returns (bytes32) {
return ProtoUtilV1.CNAME_LIQUIDITY_VAULT;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)
pragma solidity ^0.8.0;
import "./IERC3156FlashBorrower.sol";
/**
* @dev Interface of the ERC3156 FlashLender, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*
* _Available since v4.1._
*/
interface IERC3156FlashLender {
/**
* @dev The amount of currency available to be lended.
* @param token The loan currency.
* @return The amount of `token` that can be borrowed.
*/
function maxFlashLoan(address token) external view returns (uint256);
/**
* @dev The fee to be charged for a given loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @return The amount of `token` to be charged for the loan, on top of the returned principal.
*/
function flashFee(address token, uint256 amount) external view returns (uint256);
/**
* @dev Initiate a flash loan.
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/interfaces/IERC3156FlashLender.sol";
import "./VaultStrategy.sol";
abstract contract WithFlashLoan is VaultStrategy, IERC3156FlashLender {
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using NTransferUtilV2 for IERC20;
/**
* Flash loan feature
* Uses the hooks `preFlashLoan` and `postFlashLoan` on the vault delegate contract.
*
* @custom:suppress-acl This is a publicly accessible feature
* @custom:suppress-malicious-erc This ERC-20 `s.getStablecoinAddressInternal()` is a well-known address.
* @custom:suppress-pausable
* @custom:suppress-address-trust-issue The address `token` can't be manipulated via user input.
*
* @param receiver Specify the contract that receives the flash loan.
* @param token Specify the token you want to borrow.
* @param amount Enter the amount you would like to borrow.
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external override nonReentrant returns (bool) {
require(amount > 0, "Please specify amount");
/******************************************************************************************
PRE
******************************************************************************************/
(IERC20 stablecoin, uint256 fee, uint256 protocolFee) = delegate().preFlashLoan(msg.sender, key, receiver, token, amount, data);
/******************************************************************************************
BODY
******************************************************************************************/
uint256 previousBalance = stablecoin.balanceOf(address(this));
// require(previousBalance >= amount, "Balance insufficient"); <-- already checked in `preFlashLoan` --> `getFlashFeesInternal`
stablecoin.ensureTransfer(address(receiver), amount);
require(receiver.onFlashLoan(msg.sender, token, amount, fee, data) == keccak256("ERC3156FlashBorrower.onFlashLoan"), "IERC3156: Callback failed");
stablecoin.ensureTransferFrom(address(receiver), address(this), amount + fee);
uint256 finalBalance = stablecoin.balanceOf(address(this));
require(finalBalance >= previousBalance + fee, "Access is denied");
// Transfer protocol fee to the treasury
stablecoin.ensureTransfer(s.getTreasuryAddressInternal(), protocolFee);
/******************************************************************************************
POST
******************************************************************************************/
delegate().postFlashLoan(msg.sender, key, receiver, token, amount, data);
emit FlashLoanBorrowed(address(this), address(receiver), token, amount, fee);
return true;
}
/**
* @dev Gets the fee required to borrow the specified token and given amount of the loan.
*/
function flashFee(address token, uint256 amount) external view override returns (uint256) {
return delegate().getFlashFee(msg.sender, key, token, amount);
}
/**
* @dev Gets maximum amount in the specified token units that can be borrowed.
*/
function maxFlashLoan(address token) external view override returns (uint256) {
return delegate().getMaxFlashLoan(msg.sender, key, token);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashBorrower.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC3156 FlashBorrower, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*
* _Available since v4.1._
*/
interface IERC3156FlashBorrower {
/**
* @dev Receive a flash loan.
* @param initiator The initiator of the loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param fee The additional amount of tokens to repay.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
* @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
*/
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "./VaultLiquidity.sol";
pragma solidity ^0.8.0;
abstract contract VaultStrategy is VaultLiquidity {
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using NTransferUtilV2 for IERC20;
uint256 private _transferToStrategyEntry = 0;
uint256 private _receiveFromStrategyEntry = 0;
/**
* @dev Transfers tokens to strategy contract(s).
* Uses the hooks `preTransferToStrategy` and `postTransferToStrategy` on the vault delegate contract.
*
* @custom:suppress-acl This function is only callable by correct strategy contract as checked in `preTransferToStrategy` and `postTransferToStrategy`
* @custom:suppress-reentrancy Custom reentrancy guard implemented
* @custom:suppress-pausable
*
*/
function transferToStrategy(
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external override {
require(address(token) != address(0), "Invalid token to transfer");
require(coverKey == key, "Forbidden");
require(strategyName > 0, "Invalid strategy");
require(amount > 0, "Please specify amount");
// Reentrancy check
require(_transferToStrategyEntry == 0, "Access is denied");
_transferToStrategyEntry = 1;
/******************************************************************************************
PRE
******************************************************************************************/
delegate().preTransferToStrategy(msg.sender, token, coverKey, strategyName, amount);
/******************************************************************************************
BODY
******************************************************************************************/
token.ensureTransfer(msg.sender, amount);
/******************************************************************************************
POST
******************************************************************************************/
delegate().postTransferToStrategy(msg.sender, token, coverKey, strategyName, amount);
emit StrategyTransfer(address(token), msg.sender, strategyName, amount);
_transferToStrategyEntry = 0;
}
/**
* @dev Receives tokens from strategy contract(s).
* Uses the hooks `preReceiveFromStrategy` and `postReceiveFromStrategy` on the vault delegate contract.
*
* @custom:suppress-acl This function is only callable by correct strategy contract as checked in `preReceiveFromStrategy` and `postReceiveFromStrategy`
* @custom:suppress-reentrancy Custom reentrancy guard implemented
* @custom:suppress-pausable Validated in `preReceiveFromStrategy` and `postReceiveFromStrategy`
*
*/
function receiveFromStrategy(
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external override {
require(coverKey == key, "Forbidden");
require(_receiveFromStrategyEntry == 0, "Access is denied");
require(amount > 0, "Please specify amount");
_receiveFromStrategyEntry = 1;
/******************************************************************************************
PRE
******************************************************************************************/
delegate().preReceiveFromStrategy(msg.sender, token, coverKey, strategyName, amount);
/******************************************************************************************
BODY
******************************************************************************************/
token.ensureTransferFrom(msg.sender, address(this), amount);
/******************************************************************************************
POST
******************************************************************************************/
(uint256 income, uint256 loss) = delegate().postReceiveFromStrategy(msg.sender, token, coverKey, strategyName, amount);
emit StrategyReceipt(address(token), msg.sender, strategyName, amount, income, loss);
_receiveFromStrategyEntry = 0;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "./VaultBase.sol";
pragma solidity ^0.8.0;
abstract contract VaultLiquidity is VaultBase {
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using NTransferUtilV2 for IERC20;
/**
* @dev Transfers stablecoins to claims processor contracts for claims payout.
* Uses the hooks `preTransferGovernance` and `postTransferGovernance` on the vault delegate contract.
*
* @custom:suppress-acl This function is only callable by the claims processor as checked in `preTransferGovernance` and `postTransferGovernace`
* @custom:suppress-pausable
*
*/
function transferGovernance(
bytes32 coverKey,
address to,
uint256 amount
) external override nonReentrant {
require(coverKey == key, "Forbidden");
require(amount > 0, "Please specify amount");
/******************************************************************************************
PRE
******************************************************************************************/
address stablecoin = delegate().preTransferGovernance(msg.sender, coverKey, to, amount);
/******************************************************************************************
BODY
******************************************************************************************/
IERC20(stablecoin).ensureTransfer(to, amount);
/******************************************************************************************
POST
******************************************************************************************/
delegate().postTransferGovernance(msg.sender, coverKey, to, amount);
emit GovernanceTransfer(to, amount);
}
/**
* @dev Adds liquidity to the specified cover contract.
* Uses the hooks `preAddLiquidity` and `postAddLiquidity` on the vault delegate contract.
*
* @custom:suppress-acl This is a publicly accessible feature
* @custom:suppress-pausable
*
*
*/
function addLiquidity(AddLiquidityArgs calldata args) external override nonReentrant {
require(args.coverKey == key, "Forbidden");
require(args.amount > 0, "Please specify amount");
/******************************************************************************************
PRE
******************************************************************************************/
(uint256 podsToMint, uint256 previousNpmStake) = delegate().preAddLiquidity(msg.sender, args.coverKey, args.amount, args.npmStakeToAdd);
require(podsToMint > 0, "Can't determine PODs");
/******************************************************************************************
BODY
******************************************************************************************/
IERC20(sc).ensureTransferFrom(msg.sender, address(this), args.amount);
if (args.npmStakeToAdd > 0) {
IERC20(s.getNpmTokenAddressInternal()).ensureTransferFrom(msg.sender, address(this), args.npmStakeToAdd);
}
super._mint(msg.sender, podsToMint);
/******************************************************************************************
POST
******************************************************************************************/
delegate().postAddLiquidity(msg.sender, args.coverKey, args.amount, args.npmStakeToAdd);
emit PodsIssued(msg.sender, podsToMint, args.amount, args.referralCode);
if (previousNpmStake == 0) {
emit Entered(args.coverKey, msg.sender);
}
emit NpmStaken(msg.sender, args.npmStakeToAdd);
}
/**
* @dev Removes liquidity from the specified cover contract
* Uses the hooks `preRemoveLiquidity` and `postRemoveLiquidity` on the vault delegate contract.
*
* @custom:suppress-acl This is a publicly accessible feature
* @custom:suppress-pausable
*
* @param coverKey Enter the cover key
* @param podsToRedeem Enter the amount of pods to redeem
* @param npmStakeToRemove Enter the amount of NPM stake to remove.
*/
function removeLiquidity(
bytes32 coverKey,
uint256 podsToRedeem,
uint256 npmStakeToRemove,
bool exit
) external override nonReentrant {
require(coverKey == key, "Forbidden");
require(podsToRedeem > 0 || npmStakeToRemove > 0, "Please specify amount");
/******************************************************************************************
PRE
******************************************************************************************/
(address stablecoin, uint256 stablecoinToRelease) = delegate().preRemoveLiquidity(msg.sender, coverKey, podsToRedeem, npmStakeToRemove, exit);
/******************************************************************************************
BODY
******************************************************************************************/
if (podsToRedeem > 0) {
IERC20(address(this)).ensureTransferFrom(msg.sender, address(this), podsToRedeem);
IERC20(stablecoin).ensureTransfer(msg.sender, stablecoinToRelease);
}
super._burn(address(this), podsToRedeem);
// Unstake NPM tokens
if (npmStakeToRemove > 0) {
IERC20(s.getNpmTokenAddressInternal()).ensureTransfer(msg.sender, npmStakeToRemove);
}
/******************************************************************************************
POST
******************************************************************************************/
delegate().postRemoveLiquidity(msg.sender, coverKey, podsToRedeem, npmStakeToRemove, exit);
emit PodsRedeemed(msg.sender, podsToRedeem, stablecoinToRelease);
if (exit) {
emit Exited(coverKey, msg.sender);
}
if (npmStakeToRemove > 0) {
emit NpmUnstaken(msg.sender, npmStakeToRemove);
}
}
/**
* @dev Calculates the amount of PODS to mint for the given amount of liquidity to transfer
*/
function calculatePods(uint256 forStablecoinUnits) external view override returns (uint256) {
return delegate().calculatePodsImplementation(key, forStablecoinUnits);
}
/**
* @dev Calculates the amount of stablecoins to withdraw for the given amount of PODs to redeem
*/
function calculateLiquidity(uint256 podsToBurn) external view override returns (uint256) {
return delegate().calculateLiquidityImplementation(key, podsToBurn);
}
/**
* @dev Returns the stablecoin balance of this vault
* This also includes amounts lent out in lending strategies
*/
function getStablecoinBalanceOf() external view override returns (uint256) {
return delegate().getStablecoinBalanceOfImplementation(key);
}
/**
* @dev Accrues interests from external strategies
*
* @custom:suppress-acl This is a publicly accessible feature
* @custom:suppress-pausable Validated in `accrueInterestImplementation`
*
*/
function accrueInterest() external override nonReentrant {
delegate().accrueInterestImplementation(msg.sender, key);
emit InterestAccrued(key);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "../Recoverable.sol";
import "../../interfaces/IVaultDelegate.sol";
import "../../interfaces/IVault.sol";
import "../../libraries/NTransferUtilV2.sol";
pragma solidity ^0.8.0;
/**
* @title Vault Base Contract
*/
abstract contract VaultBase is ERC20, Recoverable, IVault {
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using NTransferUtilV2 for IERC20;
bytes32 public override key;
address public override sc;
/**
* @dev Constructs this contract
*
* @param store Provide store instance
* @param coverKey Provide a cover key that doesn't have a vault deployed
* @param tokenName Enter the token name of the POD. Example: `Uniswap nDAI` or `Uniswap nUSDC`
* @param tokenSymbol Enter the token symbol of the POD. Example: UNI-NDAI or `UNI-NUSDC`.
* @param stablecoin Provide an instance of the stablecoin this vault supports.
*
*/
constructor(
IStore store,
bytes32 coverKey,
string memory tokenName,
string memory tokenSymbol,
IERC20 stablecoin
) ERC20(tokenName, tokenSymbol) Recoverable(store) {
key = coverKey;
sc = address(stablecoin);
}
/**
* @dev Returns the delegate contract instance
*/
function delegate() public view returns (IVaultDelegate) {
return IVaultDelegate(s.getVaultDelegate());
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
import "./IVault.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/interfaces/IERC3156FlashLender.sol";
interface IVaultDelegate is IMember {
function preAddLiquidity(
address caller,
bytes32 coverKey,
uint256 amount,
uint256 npmStake
) external returns (uint256 podsToMint, uint256 previousNpmStake);
function postAddLiquidity(
address caller,
bytes32 coverKey,
uint256 amount,
uint256 npmStake
) external;
function accrueInterestImplementation(address caller, bytes32 coverKey) external;
function preRemoveLiquidity(
address caller,
bytes32 coverKey,
uint256 amount,
uint256 npmStake,
bool exit
) external returns (address stablecoin, uint256 stableCoinToRelease);
function postRemoveLiquidity(
address caller,
bytes32 coverKey,
uint256 amount,
uint256 npmStake,
bool exit
) external;
function preTransferGovernance(
address caller,
bytes32 coverKey,
address to,
uint256 amount
) external returns (address stablecoin);
function postTransferGovernance(
address caller,
bytes32 coverKey,
address to,
uint256 amount
) external;
function preTransferToStrategy(
address caller,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external;
function postTransferToStrategy(
address caller,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external;
function preReceiveFromStrategy(
address caller,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external;
function postReceiveFromStrategy(
address caller,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external returns (uint256 income, uint256 loss);
function preFlashLoan(
address caller,
bytes32 coverKey,
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
)
external
returns (
IERC20 stablecoin,
uint256 fee,
uint256 protocolFee
);
function postFlashLoan(
address caller,
bytes32 coverKey,
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external;
function calculatePodsImplementation(bytes32 coverKey, uint256 forStablecoinUnits) external view returns (uint256);
function calculateLiquidityImplementation(bytes32 coverKey, uint256 podsToBurn) external view returns (uint256);
function getInfoImplementation(bytes32 coverKey, address forAccount) external view returns (IVault.VaultInfoType memory);
function getStablecoinBalanceOfImplementation(bytes32 coverKey) external view returns (uint256);
function getFlashFee(
address caller,
bytes32 coverKey,
address token,
uint256 amount
) external view returns (uint256);
function getMaxFlashLoan(
address caller,
bytes32 coverKey,
address token
) external view returns (uint256);
}/* solhint-disable */
// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
library NTransferUtilV2 {
using SafeERC20 for IERC20;
/**
*
* @dev Ensures approval of ERC20-like token
* @custom:suppress-malicious-erc The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
* @custom:suppress-address-trust-issue The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
*
*/
function ensureApproval(
IERC20 malicious,
address spender,
uint256 amount
) external {
require(address(malicious) != address(0), "Invalid token address");
require(spender != address(0), "Invalid spender");
require(amount > 0, "Invalid transfer amount");
malicious.safeIncreaseAllowance(spender, amount);
}
/**
* @dev Ensures transfer of ERC20-like token
*
* @custom:suppress-malicious-erc The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
* @custom:suppress-address-trust-issue The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
* The address `recipient` can be trusted as we're not treating (or calling) it as a contract.
*
*/
function ensureTransfer(
IERC20 malicious,
address recipient,
uint256 amount
) external {
require(address(malicious) != address(0), "Invalid token address");
require(recipient != address(0), "Spender can't be zero");
require(amount > 0, "Invalid transfer amount");
uint256 balanceBeforeTransfer = malicious.balanceOf(recipient);
malicious.safeTransfer(recipient, amount);
uint256 balanceAfterTransfer = malicious.balanceOf(recipient);
// @suppress-subtraction
uint256 actualTransferAmount = balanceAfterTransfer - balanceBeforeTransfer;
require(actualTransferAmount == amount, "Invalid transfer");
}
/**
* @dev Ensures transferFrom of ERC20-like token
*
* @custom:suppress-malicious-erc The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
* @custom:suppress-address-trust-issue The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny.
* The address `recipient` can be trusted as we're not treating (or calling) it as a contract.
*
*/
function ensureTransferFrom(
IERC20 malicious,
address sender,
address recipient,
uint256 amount
) external {
require(address(malicious) != address(0), "Invalid token address");
require(sender != address(0), "Invalid sender");
require(recipient != address(0), "Invalid recipient");
require(amount > 0, "Invalid transfer amount");
uint256 balanceBeforeTransfer = malicious.balanceOf(recipient);
malicious.safeTransferFrom(sender, recipient, amount);
uint256 balanceAfterTransfer = malicious.balanceOf(recipient);
// @suppress-subtraction
uint256 actualTransferAmount = balanceAfterTransfer - balanceBeforeTransfer;
require(actualTransferAmount == amount, "Invalid transfer");
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IStore.sol";
interface IRecoverable {
function s() external view returns (IStore);
function recoverEther(address sendTo) external;
function recoverToken(address token, address sendTo) external;
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IProtocol.sol";
import "../interfaces/IPausable.sol";
library BaseLibV1 {
using SafeERC20 for IERC20;
/**
* @dev Recover all Ether held by the contract.
* On success, no event is emitted because the recovery feature does
* not have any significance in the SDK or the UI.
*/
function recoverEtherInternal(address sendTo) external {
// slither-disable-next-line low-level-calls
(bool success, ) = payable(sendTo).call{value: address(this).balance}(""); // solhint-disable-line avoid-low-level-calls
require(success, "Recipient may have reverted");
}
/**
* @dev Recover all IERC-20 compatible tokens sent to this address.
* On success, no event is emitted because the recovery feature does
* not have any significance in the SDK or the UI.
*
* @custom:suppress-malicious-erc Risk tolerable. Although the token can't be trusted, the recovery agent has to check the token code manually.
* @custom:suppress-address-trust-issue Risk tolerable. Although the token can't be trusted, the recovery agent has to check the token code manually.
*
* @param token IERC-20 The address of the token contract
*/
function recoverTokenInternal(address token, address sendTo) external {
IERC20 erc20 = IERC20(token);
uint256 balance = erc20.balanceOf(address(this));
if (balance > 0) {
// slither-disable-next-line unchecked-transfer
erc20.safeTransfer(sendTo, balance);
}
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/access/IAccessControl.sol";
import "../interfaces/IStore.sol";
import "../interfaces/IPausable.sol";
import "../interfaces/ICxToken.sol";
import "./GovernanceUtilV1.sol";
import "./AccessControlLibV1.sol";
library ValidationLibV1 {
using CoverUtilV1 for IStore;
using GovernanceUtilV1 for IStore;
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using StoreKeyUtil for IStore;
/**
* @dev Reverts if the protocol is paused
*/
function mustNotBePaused(IStore s) public view {
address protocol = s.getProtocolAddressInternal();
require(IPausable(protocol).paused() == false, "Protocol is paused");
}
/**
* @dev Reverts if the cover or any of the cover's product is not normal.
* @param coverKey Enter the cover key to check
*/
function mustEnsureAllProductsAreNormal(IStore s, bytes32 coverKey) external view {
require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, coverKey), "Cover does not exist");
require(s.isCoverNormalInternal(coverKey) == true, "Status not normal");
}
/**
* @dev Reverts if the key does not resolve in a valid cover contract
* or if the cover is under governance.
* @param coverKey Enter the cover key to check
* @param productKey Enter the product key to check
*/
function mustHaveNormalProductStatus(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, coverKey), "Cover does not exist");
require(s.getProductStatusInternal(coverKey, productKey) == CoverUtilV1.ProductStatus.Normal, "Status not normal");
}
/**
* @dev Reverts if the key does not resolve in a valid cover contract.
* @param coverKey Enter the cover key to check
*/
function mustBeValidCoverKey(IStore s, bytes32 coverKey) external view {
require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, coverKey), "Cover does not exist");
}
/**
* @dev Reverts if the cover does not support creating products.
* @param coverKey Enter the cover key to check
*/
function mustSupportProducts(IStore s, bytes32 coverKey) external view {
require(s.supportsProductsInternal(coverKey), "Does not have products");
}
/**
* @dev Reverts if the key does not resolve in a valid product of a cover contract.
* @param coverKey Enter the cover key to check
* @param productKey Enter the cover key to check
*/
function mustBeValidProduct(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
require(s.isValidProductInternal(coverKey, productKey), "Product does not exist");
}
/**
* @dev Reverts if the key resolves in an expired product.
* @param coverKey Enter the cover key to check
* @param productKey Enter the cover key to check
*/
function mustBeActiveProduct(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
require(s.isActiveProductInternal(coverKey, productKey), "Product retired or deleted");
}
/**
* @dev Reverts if the sender is not the cover owner
* @param coverKey Enter the cover key to check
* @param sender The `msg.sender` value
*/
function mustBeCoverOwner(
IStore s,
bytes32 coverKey,
address sender
) public view {
bool isCoverOwner = s.getCoverOwnerInternal(coverKey) == sender;
require(isCoverOwner, "Forbidden");
}
/**
* @dev Reverts if the sender is not the cover owner or the cover contract
* @param coverKey Enter the cover key to check
* @param sender The `msg.sender` value
*/
function mustBeCoverOwnerOrCoverContract(
IStore s,
bytes32 coverKey,
address sender
) external view {
bool isCoverOwner = s.getCoverOwnerInternal(coverKey) == sender;
bool isCoverContract = address(s.getCoverContract()) == sender;
require(isCoverOwner || isCoverContract, "Forbidden");
}
function senderMustBeCoverOwnerOrAdmin(IStore s, bytes32 coverKey) external view {
if (AccessControlLibV1.hasAccessInternal(s, AccessControlLibV1.NS_ROLES_ADMIN, msg.sender) == false) {
mustBeCoverOwner(s, coverKey, msg.sender);
}
}
function senderMustBePolicyContract(IStore s) external view {
s.senderMustBeExactContract(ProtoUtilV1.CNS_COVER_POLICY);
}
function senderMustBePolicyManagerContract(IStore s) external view {
s.senderMustBeExactContract(ProtoUtilV1.CNS_COVER_POLICY_MANAGER);
}
function senderMustBeCoverContract(IStore s) external view {
s.senderMustBeExactContract(ProtoUtilV1.CNS_COVER);
}
function senderMustBeVaultContract(IStore s, bytes32 coverKey) external view {
address vault = s.getVaultAddress(coverKey);
require(msg.sender == vault, "Forbidden");
}
function senderMustBeGovernanceContract(IStore s) external view {
s.senderMustBeExactContract(ProtoUtilV1.CNS_GOVERNANCE);
}
function senderMustBeClaimsProcessorContract(IStore s) external view {
s.senderMustBeExactContract(ProtoUtilV1.CNS_CLAIM_PROCESSOR);
}
function callerMustBeClaimsProcessorContract(IStore s, address caller) external view {
s.callerMustBeExactContract(ProtoUtilV1.CNS_CLAIM_PROCESSOR, caller);
}
function senderMustBeStrategyContract(IStore s) external view {
bool senderIsStrategyContract = s.getBoolByKey(_getIsActiveStrategyKey(msg.sender));
require(senderIsStrategyContract == true, "Not a strategy contract");
}
function callerMustBeStrategyContract(IStore s, address caller) public view {
bool isActive = s.getBoolByKey(_getIsActiveStrategyKey(caller));
bool wasDisabled = s.getBoolByKey(_getIsDisabledStrategyKey(caller));
require(isActive == true || wasDisabled == true, "Not a strategy contract");
}
function callerMustBeSpecificStrategyContract(
IStore s,
address caller,
bytes32 strategyName
) external view {
callerMustBeStrategyContract(s, caller);
require(IMember(caller).getName() == strategyName, "Access denied");
}
/**
* @dev Hash key of the "active strategy flag".
*
* Warning: this function does not validate the input arguments.
*
* @param strategyAddress Enter a strategy address
*
*/
function _getIsActiveStrategyKey(address strategyAddress) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE, strategyAddress));
}
/**
* @dev Hash key of the "disabled strategy flag".
*
* Warning: this function does not validate the input arguments.
*
* @param strategyAddress Enter a strategy address
*
*/
function _getIsDisabledStrategyKey(address strategyAddress) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED, strategyAddress));
}
function senderMustBeProtocolMember(IStore s) external view {
require(s.isProtocolMemberInternal(msg.sender), "Forbidden");
}
function mustBeReporting(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(s.getProductStatusInternal(coverKey, productKey) == CoverUtilV1.ProductStatus.IncidentHappened, "Not reporting");
}
function mustBeDisputed(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(s.getProductStatusInternal(coverKey, productKey) == CoverUtilV1.ProductStatus.FalseReporting, "Not disputed");
}
function mustBeClaimable(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
require(s.getProductStatusInternal(coverKey, productKey) == CoverUtilV1.ProductStatus.Claimable, "Not claimable");
}
function mustBeClaimingOrDisputed(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
CoverUtilV1.ProductStatus status = s.getProductStatusInternal(coverKey, productKey);
bool claiming = status == CoverUtilV1.ProductStatus.Claimable;
bool falseReporting = status == CoverUtilV1.ProductStatus.FalseReporting;
require(claiming || falseReporting, "Not claimable nor disputed");
}
function mustBeReportingOrDisputed(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
CoverUtilV1.ProductStatus status = s.getProductStatusInternal(coverKey, productKey);
bool incidentHappened = status == CoverUtilV1.ProductStatus.IncidentHappened;
bool falseReporting = status == CoverUtilV1.ProductStatus.FalseReporting;
require(incidentHappened || falseReporting, "Not reported nor disputed");
}
function mustBeBeforeResolutionDeadline(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
uint256 deadline = s.getResolutionDeadlineInternal(coverKey, productKey);
if (deadline > 0) {
require(block.timestamp < deadline, "Emergency resolution deadline over"); // solhint-disable-line
}
}
function mustNotHaveResolutionDeadline(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
uint256 deadline = s.getResolutionDeadlineInternal(coverKey, productKey);
require(deadline == 0, "Resolution already has deadline");
}
function mustBeAfterResolutionDeadline(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
uint256 deadline = s.getResolutionDeadlineInternal(coverKey, productKey);
require(deadline > 0 && block.timestamp >= deadline, "Still unresolved"); // solhint-disable-line
}
function mustBeAfterFinalization(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view {
require(s.getBoolByKey(GovernanceUtilV1.getHasFinalizedKeyInternal(coverKey, productKey, incidentDate)), "Incident not finalized");
}
function mustBeValidIncidentDate(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view {
require(s.getActiveIncidentDateInternal(coverKey, productKey) == incidentDate, "Invalid incident date");
}
function mustHaveDispute(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
bool hasDispute = s.getBoolByKey(GovernanceUtilV1.getHasDisputeKeyInternal(coverKey, productKey));
require(hasDispute == true, "Not disputed");
}
function mustNotHaveDispute(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
bool hasDispute = s.getBoolByKey(GovernanceUtilV1.getHasDisputeKeyInternal(coverKey, productKey));
require(hasDispute == false, "Already disputed");
}
function mustBeDuringReportingPeriod(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(s.getResolutionTimestampInternal(coverKey, productKey) >= block.timestamp, "Reporting window closed"); // solhint-disable-line
}
function mustBeAfterReportingPeriod(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
require(block.timestamp > s.getResolutionTimestampInternal(coverKey, productKey), "Reporting still active"); // solhint-disable-line
}
function mustBeValidCxToken(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address cxToken,
uint256 incidentDate
) public view {
require(s.getBoolByKeys(ProtoUtilV1.NS_COVER_CXTOKEN, cxToken) == true, "Unknown cxToken");
bytes32 COVER_KEY = ICxToken(cxToken).COVER_KEY(); // solhint-disable-line
bytes32 PRODUCT_KEY = ICxToken(cxToken).PRODUCT_KEY(); // solhint-disable-line
require(coverKey == COVER_KEY && productKey == PRODUCT_KEY, "Invalid cxToken");
uint256 expires = ICxToken(cxToken).expiresOn();
require(expires > incidentDate, "Invalid or expired cxToken");
}
function mustBeValidClaim(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
address cxToken,
uint256 incidentDate,
uint256 amount
) external view {
mustBeSupportedProductOrEmpty(s, coverKey, productKey);
mustBeValidCxToken(s, coverKey, productKey, cxToken, incidentDate);
mustBeClaimable(s, coverKey, productKey);
mustBeValidIncidentDate(s, coverKey, productKey, incidentDate);
mustBeDuringClaimPeriod(s, coverKey, productKey);
require(ICxToken(cxToken).getClaimablePolicyOf(account) >= amount, "Claim exceeds your coverage");
}
function mustNotHaveUnstaken(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view {
uint256 withdrawal = s.getReportingUnstakenAmountInternal(account, coverKey, productKey, incidentDate);
require(withdrawal == 0, "Already unstaken");
}
/**
* @dev Validates your `unstakeWithoutClaim` arguments
*
* @custom:note This function is not intended be used and does not produce correct result
* before an incident is finalized. Please use `validateUnstakeWithClaim` if you are accessing
* this function after resolution and before finalization.
*/
function validateUnstakeWithoutClaim(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view {
mustNotBePaused(s);
mustBeSupportedProductOrEmpty(s, coverKey, productKey);
mustNotHaveUnstaken(s, msg.sender, coverKey, productKey, incidentDate);
mustBeAfterFinalization(s, coverKey, productKey, incidentDate);
}
/**
* @dev Validates your `unstakeWithClaim` arguments
*
* @custom:note This function is only intended be used after resolution and before finalization.
* Please use `validateUnstakeWithoutClaim` if you are accessing
* this function after finalization.
*/
function validateUnstakeWithClaim(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view {
mustNotBePaused(s);
mustBeSupportedProductOrEmpty(s, coverKey, productKey);
mustNotHaveUnstaken(s, msg.sender, coverKey, productKey, incidentDate);
// If this reporting gets finalized, incident date will become invalid
// meaning this execution will revert thereby restricting late comers
// to access this feature. But they can still access `unstake` feature
// to withdraw their stake.
mustBeValidIncidentDate(s, coverKey, productKey, incidentDate);
// Before the deadline, emergency resolution can still happen
// that may have an impact on the final decision. We, therefore, have to wait.
mustBeAfterResolutionDeadline(s, coverKey, productKey);
}
function mustBeDuringClaimPeriod(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
uint256 beginsFrom = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_BEGIN_TS, coverKey, productKey);
uint256 expiresAt = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_EXPIRY_TS, coverKey, productKey);
require(beginsFrom > 0, "Invalid claim begin date");
require(expiresAt > beginsFrom, "Invalid claim period");
require(block.timestamp >= beginsFrom, "Claim period hasn't begun"); // solhint-disable-line
require(block.timestamp <= expiresAt, "Claim period has expired"); // solhint-disable-line
}
function mustBeAfterClaimExpiry(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(block.timestamp > s.getUintByKeys(ProtoUtilV1.NS_CLAIM_EXPIRY_TS, coverKey, productKey), "Claim still active"); // solhint-disable-line
}
/**
* @dev Reverts if the sender is not whitelisted cover creator.
*/
function senderMustBeWhitelistedCoverCreator(IStore s) external view {
require(s.getAddressBooleanByKey(ProtoUtilV1.NS_COVER_CREATOR_WHITELIST, msg.sender), "Not whitelisted");
}
function senderMustBeWhitelistedIfRequired(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address sender
) external view {
bool supportsProducts = s.supportsProductsInternal(coverKey);
bool required = supportsProducts ? s.checkIfProductRequiresWhitelistInternal(coverKey, productKey) : s.checkIfRequiresWhitelistInternal(coverKey);
if (required == false) {
return;
}
require(s.getAddressBooleanByKeys(ProtoUtilV1.NS_COVER_USER_WHITELIST, coverKey, productKey, sender), "You are not whitelisted");
}
function mustBeSupportedProductOrEmpty(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view {
bool hasProducts = s.supportsProductsInternal(coverKey);
hasProducts ? require(productKey > 0, "Specify a product") : require(productKey == 0, "Invalid product");
if (hasProducts) {
mustBeValidProduct(s, coverKey, productKey);
mustBeActiveProduct(s, coverKey, productKey);
}
}
function mustNotHavePolicyDisabled(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view {
require(!s.isPolicyDisabledInternal(coverKey, productKey), "Policy purchase disabled");
}
function mustMaintainStablecoinThreshold(IStore s, uint256 amount) external view {
uint256 stablecoinPrecision = s.getStablecoinPrecisionInternal();
require(amount >= ProtoUtilV1.MIN_LIQUIDITY * stablecoinPrecision, "Liquidity is below threshold");
require(amount <= ProtoUtilV1.MAX_LIQUIDITY * stablecoinPrecision, "Liquidity is above threshold");
}
function mustMaintainProposalThreshold(IStore s, uint256 amount) external view {
uint256 stablecoinPrecision = s.getStablecoinPrecisionInternal();
require(amount >= ProtoUtilV1.MIN_PROPOSAL_AMOUNT * stablecoinPrecision, "Proposal is below threshold");
require(amount <= ProtoUtilV1.MAX_PROPOSAL_AMOUNT * stablecoinPrecision, "Proposal is above threshold");
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/access/IAccessControl.sol";
import "./IMember.sol";
interface IProtocol is IMember, IAccessControl {
struct AccountWithRoles {
address account;
bytes32[] roles;
}
struct InitializeArgs {
address burner;
address uniswapV2RouterLike;
address uniswapV2FactoryLike;
address npm;
address treasury;
address priceOracle;
uint256 coverCreationFee;
uint256 minCoverCreationStake;
uint256 minStakeToAddLiquidity;
uint256 firstReportingStake;
uint256 claimPeriod;
uint256 reportingBurnRate;
uint256 governanceReporterCommission;
uint256 claimPlatformFee;
uint256 claimReporterCommission;
uint256 flashLoanFee;
uint256 flashLoanFeeProtocol;
uint256 resolutionCoolDownPeriod;
uint256 stateUpdateInterval;
uint256 maxLendingRatio;
uint256 lendingPeriod;
uint256 withdrawalWindow;
uint256 policyFloor;
uint256 policyCeiling;
}
event Initialized(InitializeArgs args);
event ContractAdded(bytes32 indexed namespace, bytes32 indexed key, address indexed contractAddress);
event ContractUpgraded(bytes32 indexed namespace, bytes32 indexed key, address previous, address indexed current);
event MemberAdded(address member);
event MemberRemoved(address member);
function addContract(bytes32 namespace, address contractAddress) external;
function addContracts(
bytes32[] calldata namespaces,
bytes32[] calldata keys,
address[] calldata contractAddresses
) external;
function addContractWithKey(
bytes32 namespace,
bytes32 coverKey,
address contractAddress
) external;
function initialize(InitializeArgs calldata args) external;
function upgradeContract(
bytes32 namespace,
address previous,
address current
) external;
function upgradeContractWithKey(
bytes32 namespace,
bytes32 coverKey,
address previous,
address current
) external;
function addMember(address member) external;
function removeMember(address member) external;
function grantRoles(AccountWithRoles[] calldata detail) external;
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IPausable {
function paused() external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
pragma solidity ^0.8.0;
interface ICxToken is IERC20 {
event CoverageStartSet(uint256 policyId, bytes32 coverKey, bytes32 productKey, address account, uint256 effectiveFrom, uint256 amount);
function mint(
uint256 policyId,
bytes32 coverKey,
bytes32 productKey,
address to,
uint256 amount
) external;
function burn(uint256 amount) external;
function createdOn() external view returns (uint256);
function expiresOn() external view returns (uint256);
// slither-disable-next-line naming-convention
function COVER_KEY() external view returns (bytes32); // solhint-disable
// slither-disable-next-line naming-convention
function PRODUCT_KEY() external view returns (bytes32); // solhint-disable
function getCoverageStartsFrom(address account, uint256 date) external view returns (uint256);
function getClaimablePolicyOf(address account) external view returns (uint256);
}/* solhint-disable function-max-lines */
// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IStore.sol";
import "../interfaces/IPolicy.sol";
import "../interfaces/ICoverStake.sol";
import "../interfaces/IUnstakable.sol";
import "../interfaces/ICoverReassurance.sol";
import "../interfaces/IVault.sol";
import "../interfaces/IVaultFactory.sol";
import "./RoutineInvokerLibV1.sol";
library GovernanceUtilV1 {
using CoverUtilV1 for IStore;
using RoutineInvokerLibV1 for IStore;
using StoreKeyUtil for IStore;
/**
* @dev Gets the reporting period for the given cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
*
*/
function getReportingPeriodInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_PERIOD, coverKey);
}
/**
* @dev Gets the NPM stake burn rate (upon resolution) for the given cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
*
*/
function getReportingBurnRateInternal(IStore s) public view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_GOVERNANCE_REPORTING_BURN_RATE);
}
/**
* @dev Gets the "valid" reporter's NPM commission rate
* (upon each unstake claim invoked by individual "valid" stakers)
* for the given cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
*
*/
function getGovernanceReporterCommissionInternal(IStore s) public view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_GOVERNANCE_REPORTER_COMMISSION);
}
/**
* @dev Gets the protocol's NPM commission rate
* (upon each unstake claim invoked by individual "valid" stakers)
* for the given cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
*
*/
function getPlatformCoverFeeRateInternal(IStore s) external view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_COVER_PLATFORM_FEE);
}
/**
* @dev Gets the "valid" reporter's stablecoin commission rate
* on protocol's earnings (upon each claim payout received by claimants)
* for the given cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
*
*/
function getClaimReporterCommissionInternal(IStore s) external view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_CLAIM_REPORTER_COMMISSION);
}
/**
* @dev Gets the minimum units of NPM tokens required to report the supplied cover.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
*
*/
function getMinReportingStakeInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
uint256 fb = s.getUintByKey(ProtoUtilV1.NS_GOVERNANCE_REPORTING_MIN_FIRST_STAKE);
uint256 custom = s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_MIN_FIRST_STAKE, coverKey);
return custom > 0 ? custom : fb;
}
/**
* @dev Gets a cover's resolution timestamp.
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getResolutionTimestampInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (uint256) {
return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_RESOLUTION_TS, coverKey, productKey);
}
/**
* @dev Gets the given cover incident's reporter.
* Note that this keeps changing between "first reporter"
* and "candidate reporter" until resolution is achieved.
*
* <br /> <br />
*
* [Read More](https://docs.neptunemutual.com/covers/cover-reporting)
*
* <br /> <br />
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getReporterInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (address) {
CoverUtilV1.ProductStatus status = s.getProductStatusOfInternal(coverKey, productKey, incidentDate);
bool incidentHappened = status == CoverUtilV1.ProductStatus.IncidentHappened || status == CoverUtilV1.ProductStatus.Claimable;
bytes32 prefix = incidentHappened ? ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES : ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO;
return s.getAddressByKeys(prefix, coverKey, productKey);
}
/**
* @dev Returns stakes of the given cover product's incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getStakesInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (uint256 yes, uint256 no) {
yes = s.getUintByKey(_getIncidentOccurredStakesKey(coverKey, productKey, incidentDate));
no = s.getUintByKey(_getFalseReportingStakesKey(coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of the reporter for the given cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getReporterKey(bytes32 coverKey, bytes32 productKey) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES, coverKey, productKey));
}
/**
* @dev Hash key of the stakes added under `Incident Happened` camp for the given cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getIncidentOccurredStakesKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES, coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of the claims payout given for the supplied cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getClaimPayoutsKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_CLAIM_PAYOUTS, coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of the reassurance payout granted for the supplied cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getReassurancePayoutKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_REASSURANCE_PAYOUT, coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of an individual's stakes added under `Incident Happened` camp for the given cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getIndividualIncidentOccurredStakeKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
address account
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_STAKE_OWNED_YES, coverKey, productKey, incidentDate, account));
}
/**
* @dev Hash key of the "candidate reporter" for the supplied cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getDisputerKey(bytes32 coverKey, bytes32 productKey) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO, coverKey, productKey));
}
/**
* @dev Hash key of the stakes added under `False Reporting` camp for the given cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getFalseReportingStakesKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO, coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of an individual's stakes added under `False Reporting` camp for the given cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function _getIndividualFalseReportingStakeKey(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
address account
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_STAKE_OWNED_NO, coverKey, productKey, incidentDate, account));
}
/**
* @dev Returns stakes of the given account for a cover product's incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param account Specify the account to get stakes
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getStakesOfInternal(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (uint256 yes, uint256 no) {
yes = s.getUintByKey(_getIndividualIncidentOccurredStakeKey(coverKey, productKey, incidentDate, account));
no = s.getUintByKey(_getIndividualFalseReportingStakeKey(coverKey, productKey, incidentDate, account));
}
/**
* @dev Returns resolution info of the given account
* for a cover product's incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param account Specify the account to get stakes
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
* @param totalStakeInWinningCamp Total NPM tokens in currently "winning" camp.
* @param totalStakeInLosingCamp Total NPM tokens in currently "losing" camp.
* @param myStakeInWinningCamp Your NPM tokens in the "winning" camp.
*
*/
function getResolutionInfoForInternal(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
)
public
view
returns (
uint256 totalStakeInWinningCamp,
uint256 totalStakeInLosingCamp,
uint256 myStakeInWinningCamp
)
{
(uint256 yes, uint256 no) = getStakesInternal(s, coverKey, productKey, incidentDate);
(uint256 myYes, uint256 myNo) = getStakesOfInternal(s, account, coverKey, productKey, incidentDate);
CoverUtilV1.ProductStatus decision = s.getProductStatusOfInternal(coverKey, productKey, incidentDate);
bool incidentHappened = decision == CoverUtilV1.ProductStatus.IncidentHappened || decision == CoverUtilV1.ProductStatus.Claimable;
totalStakeInWinningCamp = incidentHappened ? yes : no;
totalStakeInLosingCamp = incidentHappened ? no : yes;
myStakeInWinningCamp = incidentHappened ? myYes : myNo;
}
/**
* @dev Returns unstake info of the given account
* for a cover product's incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param account Specify the account to get stakes
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getUnstakeInfoForInternal(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (IUnstakable.UnstakeInfoType memory info) {
(info.totalStakeInWinningCamp, info.totalStakeInLosingCamp, info.myStakeInWinningCamp) = getResolutionInfoForInternal(s, account, coverKey, productKey, incidentDate);
info.unstaken = getReportingUnstakenAmountInternal(s, account, coverKey, productKey, incidentDate);
require(info.myStakeInWinningCamp > 0, "Nothing to unstake");
uint256 rewardRatio = (info.myStakeInWinningCamp * ProtoUtilV1.MULTIPLIER) / info.totalStakeInWinningCamp;
uint256 reward = 0;
// Incident dates are reset when a reporting is finalized.
// This check ensures only the people who come to unstake
// before the finalization will receive rewards
if (s.getActiveIncidentDateInternal(coverKey, productKey) == incidentDate) {
// slither-disable-next-line divide-before-multiply
reward = (info.totalStakeInLosingCamp * rewardRatio) / ProtoUtilV1.MULTIPLIER;
}
require(getReportingBurnRateInternal(s) + getGovernanceReporterCommissionInternal(s) <= ProtoUtilV1.MULTIPLIER, "Invalid configuration");
info.toBurn = (reward * getReportingBurnRateInternal(s)) / ProtoUtilV1.MULTIPLIER;
info.toReporter = (reward * getGovernanceReporterCommissionInternal(s)) / ProtoUtilV1.MULTIPLIER;
info.myReward = reward - info.toBurn - info.toReporter;
}
/**
* @dev Returns NPM already unstaken by the specified account for a cover incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param account Specify the account to get stakes
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getReportingUnstakenAmountInternal(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (uint256) {
bytes32 k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, coverKey, productKey, incidentDate, account));
return s.getUintByKey(k);
}
function updateUnstakeDetailsInternal(
IStore s,
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
uint256 originalStake,
uint256 reward,
uint256 burned,
uint256 reporterFee
) external {
// Unstake timestamp of the account
bytes32 k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_TS, coverKey, productKey, incidentDate, account));
s.setUintByKey(k, block.timestamp); // solhint-disable-line
// Last unstake timestamp
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_TS, coverKey, productKey, incidentDate));
s.setUintByKey(k, block.timestamp); // solhint-disable-line
// ---------------------------------------------------------------------
// Amount unstaken by the account
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, coverKey, productKey, incidentDate, account));
s.setUintByKey(k, originalStake);
// Amount unstaken by everyone
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, coverKey, productKey, incidentDate));
s.addUintByKey(k, originalStake);
// ---------------------------------------------------------------------
if (reward > 0) {
// Reward received by the account
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_REWARD, coverKey, productKey, incidentDate, account));
s.setUintByKey(k, reward);
// Total reward received
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_REWARD, coverKey, productKey, incidentDate));
s.addUintByKey(k, reward);
}
// ---------------------------------------------------------------------
if (burned > 0) {
// Total burned
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_BURNED, coverKey, productKey, incidentDate));
s.addUintByKey(k, burned);
}
if (reporterFee > 0) {
// Total fee paid to the final reporter
k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_REPORTER_FEE, coverKey, productKey, incidentDate));
s.addUintByKey(k, reporterFee);
}
}
function _updateProductStatusBeforeResolutionInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) private {
require(incidentDate > 0, "Invalid incident date");
uint256 yes = s.getUintByKey(_getIncidentOccurredStakesKey(coverKey, productKey, incidentDate));
uint256 no = s.getUintByKey(_getFalseReportingStakesKey(coverKey, productKey, incidentDate));
if (no > yes) {
s.setStatusInternal(coverKey, productKey, incidentDate, CoverUtilV1.ProductStatus.FalseReporting);
return;
}
s.setStatusInternal(coverKey, productKey, incidentDate, CoverUtilV1.ProductStatus.IncidentHappened);
}
/**
* @dev Adds attestation to an incident report
*
* @custom:suppress-address-trust-issue The address `who` can be trusted here because we are not treating it like a contract.
*
*/
function addAttestationInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate,
uint256 stake
) external {
mustNotExceedNpmThreshold(stake);
// Add individual stake of the reporter
s.addUintByKey(_getIndividualIncidentOccurredStakeKey(coverKey, productKey, incidentDate, who), stake);
// All "incident happened" camp witnesses combined
uint256 currentStake = s.getUintByKey(_getIncidentOccurredStakesKey(coverKey, productKey, incidentDate));
// No has reported yet, this is the first report
if (currentStake == 0) {
s.setAddressByKey(_getReporterKey(coverKey, productKey), who);
}
s.addUintByKey(_getIncidentOccurredStakesKey(coverKey, productKey, incidentDate), stake);
_updateProductStatusBeforeResolutionInternal(s, coverKey, productKey, incidentDate);
s.updateStateAndLiquidityInternal(coverKey);
}
/**
* @dev Returns sum total of NPM staken under `Incident Happened` camp.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param who Specify the account to get attestation info
* @param incidentDate Enter incident date
*
* @param myStake The total NPM amount (under incident happened or yes) you have staken for this trigger incident.
* @param totalStake The total NPM amount (under incident happened or yes) staken by all tokenholders.
*
*/
function getAttestationInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate
) external view returns (uint256 myStake, uint256 totalStake) {
myStake = s.getUintByKey(_getIndividualIncidentOccurredStakeKey(coverKey, productKey, incidentDate, who));
totalStake = s.getUintByKey(_getIncidentOccurredStakesKey(coverKey, productKey, incidentDate));
}
/**
* @dev Adds refutation to an incident report
*
* @custom:suppress-address-trust-issue The address `who` can be trusted here because we are not treating it like a contract.
*
*/
function addRefutationInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate,
uint256 stake
) external {
mustNotExceedNpmThreshold(stake);
s.addUintByKey(_getIndividualFalseReportingStakeKey(coverKey, productKey, incidentDate, who), stake);
uint256 currentStake = s.getUintByKey(_getFalseReportingStakesKey(coverKey, productKey, incidentDate));
if (currentStake == 0) {
// The first reporter who disputed
s.setAddressByKey(_getDisputerKey(coverKey, productKey), who);
s.setBoolByKey(getHasDisputeKeyInternal(coverKey, productKey), true);
}
s.addUintByKey(_getFalseReportingStakesKey(coverKey, productKey, incidentDate), stake);
_updateProductStatusBeforeResolutionInternal(s, coverKey, productKey, incidentDate);
s.updateStateAndLiquidityInternal(coverKey);
}
/**
* @dev Hash key of the "has dispute flag" for the specified cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getHasDisputeKeyInternal(bytes32 coverKey, bytes32 productKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_HAS_A_DISPUTE, coverKey, productKey));
}
/**
* @dev Hash key of the "has finalized flag" for the specified cover product.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getHasFinalizedKeyInternal(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_FINALIZATION, coverKey, productKey, incidentDate));
}
/**
* @dev Returns sum total of NPM staken under `False Reporting` camp.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param who Specify the account to get attestation info
* @param incidentDate Enter incident date
*
* @param myStake The total NPM amount (under false reporting or no) you have staken for this trigger incident.
* @param totalStake The total NPM amount (under false reporting or no) staken by all tokenholders.
*
*/
function getRefutationInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate
) external view returns (uint256 myStake, uint256 totalStake) {
myStake = s.getUintByKey(_getIndividualFalseReportingStakeKey(coverKey, productKey, incidentDate, who));
totalStake = s.getUintByKey(_getFalseReportingStakesKey(coverKey, productKey, incidentDate));
}
/**
* @dev Returns cooldown period. Cooldown period is a defense
* against [collusion and last-block attacks](https://docs.neptunemutual.com/covers/cover-reporting#collusion-and-last-block-attacks).
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
*
*/
function getCoolDownPeriodInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
uint256 fromKey = s.getUintByKeys(ProtoUtilV1.NS_RESOLUTION_COOL_DOWN_PERIOD, coverKey);
uint256 fallbackValue = s.getUintByKey(ProtoUtilV1.NS_RESOLUTION_COOL_DOWN_PERIOD);
return fromKey > 0 ? fromKey : fallbackValue;
}
/**
* @dev The date and time prior to which a governance administrator
* may still initiate a "emergency resolution."
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getResolutionDeadlineInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (uint256) {
return s.getUintByKeys(ProtoUtilV1.NS_RESOLUTION_DEADLINE, coverKey, productKey);
}
function addClaimPayoutsInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
uint256 claimed
) external {
s.addUintByKey(_getClaimPayoutsKey(coverKey, productKey, incidentDate), claimed);
}
/**
* @dev Returns the total amount of payouts awarded to claimants for this incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getClaimPayoutsInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (uint256) {
return s.getUintByKey(_getClaimPayoutsKey(coverKey, productKey, incidentDate));
}
/**
* @dev Returns the total amount of reassurance granted to vault for this incident.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getReassurancePayoutInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (uint256) {
return s.getUintByKey(_getReassurancePayoutKey(coverKey, productKey, incidentDate));
}
function addReassurancePayoutInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
uint256 capitalized
) external {
s.addUintByKey(_getReassurancePayoutKey(coverKey, productKey, incidentDate), capitalized);
}
/**
* @dev Returns the remaining reassurance amount that can be transferred
* to the vault following the claim period but prior to finalisation.
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getReassuranceTransferrableInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (uint256) {
uint256 reassuranceRate = s.getReassuranceRateInternal(coverKey);
uint256 available = s.getReassuranceAmountInternal(coverKey);
uint256 reassurancePaid = getReassurancePayoutInternal(s, coverKey, productKey, incidentDate);
uint256 totalReassurance = available + reassurancePaid;
uint256 claimsPaid = getClaimPayoutsInternal(s, coverKey, productKey, incidentDate);
uint256 principal = claimsPaid <= totalReassurance ? claimsPaid : totalReassurance;
uint256 transferAmount = (principal * reassuranceRate) / ProtoUtilV1.MULTIPLIER;
return transferAmount - reassurancePaid;
}
function mustNotExceedNpmThreshold(uint256 amount) public pure {
require(amount <= ProtoUtilV1.MAX_NPM_STAKE * 1 ether, "NPM stake is above threshold");
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/access/IAccessControl.sol";
import "./ProtoUtilV1.sol";
library AccessControlLibV1 {
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
bytes32 public constant NS_ROLES_ADMIN = 0x00; // SAME AS "DEFAULT_ADMIN_ROLE"
bytes32 public constant NS_ROLES_COVER_MANAGER = "role:cover:manager";
bytes32 public constant NS_ROLES_LIQUIDITY_MANAGER = "role:liquidity:manager";
bytes32 public constant NS_ROLES_GOVERNANCE_AGENT = "role:governance:agent";
bytes32 public constant NS_ROLES_GOVERNANCE_ADMIN = "role:governance:admin";
bytes32 public constant NS_ROLES_UPGRADE_AGENT = "role:upgrade:agent";
bytes32 public constant NS_ROLES_RECOVERY_AGENT = "role:recovery:agent";
bytes32 public constant NS_ROLES_PAUSE_AGENT = "role:pause:agent";
bytes32 public constant NS_ROLES_UNPAUSE_AGENT = "role:unpause:agent";
/**
* @dev Reverts if the sender is not the protocol admin.
*/
function mustBeAdmin(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_ADMIN, msg.sender);
}
/**
* @dev Reverts if the sender is not the cover manager.
*/
function mustBeCoverManager(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_COVER_MANAGER, msg.sender);
}
/**
* @dev Reverts if the sender is not the liquidity manager.
*/
function mustBeLiquidityManager(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_LIQUIDITY_MANAGER, msg.sender);
}
/**
* @dev Reverts if the sender is not a governance agent.
*/
function mustBeGovernanceAgent(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_GOVERNANCE_AGENT, msg.sender);
}
/**
* @dev Reverts if the sender is not a governance admin.
*/
function mustBeGovernanceAdmin(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_GOVERNANCE_ADMIN, msg.sender);
}
/**
* @dev Reverts if the sender is not an upgrade agent.
*/
function mustBeUpgradeAgent(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_UPGRADE_AGENT, msg.sender);
}
/**
* @dev Reverts if the sender is not a recovery agent.
*/
function mustBeRecoveryAgent(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_RECOVERY_AGENT, msg.sender);
}
/**
* @dev Reverts if the sender is not the pause agent.
*/
function mustBePauseAgent(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_PAUSE_AGENT, msg.sender);
}
/**
* @dev Reverts if the sender is not the unpause agent.
*/
function mustBeUnpauseAgent(IStore s) external view {
_mustHaveAccess(s, NS_ROLES_UNPAUSE_AGENT, msg.sender);
}
/**
* @dev Reverts if the caller is not the protocol admin.
*/
function callerMustBeAdmin(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_ADMIN, caller);
}
/**
* @dev Reverts if the caller is not the cover manager.
*/
function callerMustBeCoverManager(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_COVER_MANAGER, caller);
}
/**
* @dev Reverts if the caller is not the liquidity manager.
*/
function callerMustBeLiquidityManager(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_LIQUIDITY_MANAGER, caller);
}
/**
* @dev Reverts if the caller is not a governance agent.
*/
function callerMustBeGovernanceAgent(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_GOVERNANCE_AGENT, caller);
}
/**
* @dev Reverts if the caller is not a governance admin.
*/
function callerMustBeGovernanceAdmin(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_GOVERNANCE_ADMIN, caller);
}
/**
* @dev Reverts if the caller is not an upgrade agent.
*/
function callerMustBeUpgradeAgent(IStore s, address caller) public view {
_mustHaveAccess(s, NS_ROLES_UPGRADE_AGENT, caller);
}
/**
* @dev Reverts if the caller is not a recovery agent.
*/
function callerMustBeRecoveryAgent(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_RECOVERY_AGENT, caller);
}
/**
* @dev Reverts if the caller is not the pause agent.
*/
function callerMustBePauseAgent(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_PAUSE_AGENT, caller);
}
/**
* @dev Reverts if the caller is not the unpause agent.
*/
function callerMustBeUnpauseAgent(IStore s, address caller) external view {
_mustHaveAccess(s, NS_ROLES_UNPAUSE_AGENT, caller);
}
/**
* @dev Reverts if the caller does not have access to the given role.
*/
function _mustHaveAccess(
IStore s,
bytes32 role,
address caller
) private view {
require(hasAccessInternal(s, role, caller), "Forbidden");
}
/**
* @dev Checks if a given user has access to the given role
* @param role Specify the role name
* @param user Enter the user account
* @return Returns true if the user is a member of the specified role
*/
function hasAccessInternal(
IStore s,
bytes32 role,
address user
) public view returns (bool) {
address protocol = s.getProtocolAddressInternal();
// The protocol is not deployed yet. Therefore, no role to check
if (protocol == address(0)) {
return false;
}
// You must have the same role in the protocol contract if you're don't have this role here
return IAccessControl(protocol).hasRole(role, user);
}
/**
* @dev Adds a protocol member contract
*
* @custom:suppress-address-trust-issue This feature can only be accessed internally within the protocol.
*
* @param s Enter the store instance
* @param namespace Enter the contract namespace
* @param key Enter the contract key
* @param contractAddress Enter the contract address
*/
function addContractInternal(
IStore s,
bytes32 namespace,
bytes32 key,
address contractAddress
) external {
// Not only the msg.sender needs to be an upgrade agent
// but the contract using this library (and this function)
// must also be an upgrade agent
callerMustBeUpgradeAgent(s, address(this));
_addContract(s, namespace, key, contractAddress);
}
function _addContract(
IStore s,
bytes32 namespace,
bytes32 key,
address contractAddress
) private {
if (key > 0) {
s.setAddressByKeys(ProtoUtilV1.NS_CONTRACTS, namespace, key, contractAddress);
} else {
s.setAddressByKeys(ProtoUtilV1.NS_CONTRACTS, namespace, contractAddress);
}
_addMember(s, contractAddress);
}
function _deleteContract(
IStore s,
bytes32 namespace,
bytes32 key,
address contractAddress
) private {
if (key > 0) {
s.deleteAddressByKeys(ProtoUtilV1.NS_CONTRACTS, namespace, key);
} else {
s.deleteAddressByKeys(ProtoUtilV1.NS_CONTRACTS, namespace);
}
_removeMember(s, contractAddress);
}
/**
* @dev Upgrades a contract at the given namespace and key.
*
* The previous contract's protocol membership is revoked and
* the current immediately starts assuming responsibility of
* whatever the contract needs to do at the supplied namespace and key.
*
* @custom:warning Warning:
*
* This feature is only accessible to an upgrade agent.
* Since adding member to the protocol is a highly risky activity,
* the role `Upgrade Agent` is considered to be one of the most `Critical` roles.
*
* @custom:suppress-address-trust-issue This feature can only be accessed internally within the protocol.
*
* @param s Provide store instance
* @param namespace Enter a unique namespace for this contract
* @param key Enter a key if this contract has siblings
* @param previous Enter the existing contract address at this namespace and key.
* @param current Enter the contract address which will replace the previous contract.
*/
function upgradeContractInternal(
IStore s,
bytes32 namespace,
bytes32 key,
address previous,
address current
) external {
// Not only the msg.sender needs to be an upgrade agent
// but the contract using this library (and this function)
// must also be an upgrade agent
callerMustBeUpgradeAgent(s, address(this));
bool isMember = s.isProtocolMemberInternal(previous);
require(isMember, "Not a protocol member");
_deleteContract(s, namespace, key, previous);
_addContract(s, namespace, key, current);
}
/**
* @dev Adds member to the protocol
*
* A member is a trusted EOA or a contract that was added to the protocol using `addContract`
* function. When a contract is removed using `upgradeContract` function, the membership of previous
* contract is also removed.
*
* @custom:warning Warning:
*
* This feature is only accessible to an upgrade agent.
* Since adding member to the protocol is a highly risky activity,
* the role `Upgrade Agent` is considered to be one of the most `Critical` roles.
*
* @custom:suppress-address-trust-issue This feature can only be accessed internally within the protocol.
*
* @param member Enter an address to add as a protocol member
*/
function addMemberInternal(IStore s, address member) external {
// Not only the msg.sender needs to be an upgrade agent
// but the contract using this library (and this function)
// must also be an upgrade agent
callerMustBeUpgradeAgent(s, address(this));
_addMember(s, member);
}
/**
* @dev Removes a member from the protocol. This function is only accessible
* to an upgrade agent.
*
* @custom:suppress-address-trust-issue This feature can only be accessed internally within the protocol.
*
* @param member Enter an address to remove as a protocol member
*/
function removeMemberInternal(IStore s, address member) external {
// Not only the msg.sender needs to be an upgrade agent
// but the contract using this library (and this function)
// must also be an upgrade agent
callerMustBeUpgradeAgent(s, address(this));
_removeMember(s, member);
}
function _addMember(IStore s, address member) private {
require(s.getBoolByKeys(ProtoUtilV1.NS_MEMBERS, member) == false, "Already exists");
s.setBoolByKeys(ProtoUtilV1.NS_MEMBERS, member, true);
}
function _removeMember(IStore s, address member) private {
s.deleteBoolByKeys(ProtoUtilV1.NS_MEMBERS, member);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
interface IPolicy is IMember {
struct PurchaseCoverArgs {
address onBehalfOf;
bytes32 coverKey;
bytes32 productKey;
uint256 coverDuration;
uint256 amountToCover;
bytes32 referralCode;
}
struct CoverFeeInfoType {
uint256 fee;
uint256 utilizationRatio;
uint256 totalAvailableLiquidity;
uint256 floor;
uint256 ceiling;
uint256 rate;
}
struct CoverPoolSummaryType {
uint256 totalAmountInPool;
uint256 totalCommitment;
uint256 reassuranceAmount;
uint256 reassurancePoolWeight;
uint256 productCount;
uint256 leverage;
uint256 productCapitalEfficiency;
}
event CoverPurchased(PurchaseCoverArgs args, address indexed cxToken, uint256 fee, uint256 platformFee, uint256 expiresOn, uint256 policyId);
/**
* @dev Purchase cover for the specified amount. <br /> <br />
* When you purchase covers, you receive equal amount of cxTokens back.
* You need the cxTokens to claim the cover when resolution occurs.
* Each unit of cxTokens are fully redeemable at 1:1 ratio to the given
* stablecoins (like wxDai, DAI, USDC, or BUSD) based on the chain.
*/
function purchaseCover(PurchaseCoverArgs calldata args) external returns (address, uint256);
/**
* @dev Gets the cover fee info for the given cover key, duration, and amount
* @param coverKey Enter the cover key
* @param productKey Enter the product key
* @param coverDuration Enter the number of months to cover. Accepted values: 1-3.
* @param amountToCover Enter the amount of the stablecoin to cover.
*/
function getCoverFeeInfo(
bytes32 coverKey,
bytes32 productKey,
uint256 coverDuration,
uint256 amountToCover
) external view returns (CoverFeeInfoType memory);
/**
* @dev Returns pool summary of the given cover key
*/
function getCoverPoolSummary(bytes32 coverKey, bytes32 productKey) external view returns (CoverPoolSummaryType memory summary);
function getCxToken(
bytes32 coverKey,
bytes32 productKey,
uint256 coverDuration
) external view returns (address cxToken, uint256 expiryDate);
function getCxTokenByExpiryDate(
bytes32 coverKey,
bytes32 productKey,
uint256 expiryDate
) external view returns (address cxToken);
/**
* Gets the sum total of cover commitment that haven't expired yet.
*/
function getCommitment(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
/**
* Gets the available liquidity in the pool.
*/
function getAvailableLiquidity(bytes32 coverKey) external view returns (uint256);
/**
* @dev Gets the expiry date based on cover duration
* @param today Enter the current timestamp
* @param coverDuration Enter the number of months to cover. Accepted values: 1-3.
*/
function getExpiryDate(uint256 today, uint256 coverDuration) external pure returns (uint256);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
interface ICoverStake is IMember {
event StakeAdded(bytes32 indexed coverKey, address indexed account, uint256 amount);
event StakeRemoved(bytes32 indexed coverKey, address indexed account, uint256 amount);
event FeeBurned(bytes32 indexed coverKey, uint256 amount);
/**
* @dev Increase the stake of the given cover pool
* @param coverKey Enter the cover key
* @param account Enter the account from where the NPM tokens will be transferred
* @param amount Enter the amount of stake
* @param fee Enter the fee amount. Note: do not enter the fee if you are directly calling this function.
*/
function increaseStake(
bytes32 coverKey,
address account,
uint256 amount,
uint256 fee
) external;
/**
* @dev Decreases the stake from the given cover pool
* @param coverKey Enter the cover key
* @param amount Enter the amount of stake to decrease
*/
function decreaseStake(bytes32 coverKey, uint256 amount) external;
/**
* @dev Gets the stake of an account for the given cover key
* @param coverKey Enter the cover key
* @param account Specify the account to obtain the stake of
* @return Returns the total stake of the specified account on the given cover key
*/
function stakeOf(bytes32 coverKey, address account) external view returns (uint256);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IStore.sol";
interface IUnstakable {
struct UnstakeInfoType {
uint256 totalStakeInWinningCamp;
uint256 totalStakeInLosingCamp;
uint256 myStakeInWinningCamp;
uint256 toBurn;
uint256 toReporter;
uint256 myReward;
uint256 unstaken;
}
event Unstaken(bytes32 indexed coverKey, bytes32 indexed productKey, address indexed caller, uint256 originalStake, uint256 reward);
event ReporterRewardDistributed(bytes32 indexed coverKey, bytes32 indexed productKey, address caller, address indexed reporter, uint256 originalReward, uint256 reporterReward);
event GovernanceBurned(bytes32 indexed coverKey, bytes32 indexed productKey, address caller, address indexed burner, uint256 originalReward, uint256 burnedAmount);
function unstake(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external;
function unstakeWithClaim(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external;
function getUnstakeInfoFor(
address account,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (UnstakeInfoType memory);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
interface ICoverReassurance is IMember {
event ReassuranceAdded(bytes32 indexed coverKey, address indexed onBehalfOf, uint256 amount);
event WeightSet(bytes32 indexed coverKey, uint256 weight);
event PoolCapitalized(bytes32 indexed coverKey, bytes32 indexed productKey, uint256 indexed incidentDate, uint256 amount);
/**
* @dev Adds reassurance to the specified cover contract
* @param coverKey Enter the cover key
* @param onBehalfOf Enter the account on behalf of which you are adding reassurance.
* @param amount Enter the amount you would like to supply
*/
function addReassurance(
bytes32 coverKey,
address onBehalfOf,
uint256 amount
) external;
function setWeight(bytes32 coverKey, uint256 weight) external;
function capitalizePool(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external;
/**
* @dev Gets the reassurance amount of the specified cover contract
* @param coverKey Enter the cover key
*/
function getReassurance(bytes32 coverKey) external view returns (uint256);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IStore.sol";
import "../interfaces/ILendingStrategy.sol";
import "./PriceLibV1.sol";
import "./CoverUtilV1.sol";
library RoutineInvokerLibV1 {
using CoverUtilV1 for IStore;
using PriceLibV1 for IStore;
using ProtoUtilV1 for IStore;
using RegistryLibV1 for IStore;
using StoreKeyUtil for IStore;
using StrategyLibV1 for IStore;
enum Action {
Deposit,
Withdraw
}
function updateStateAndLiquidityInternal(IStore s, bytes32 coverKey) external {
_invoke(s, coverKey);
}
function _invoke(IStore s, bytes32 coverKey) private {
// solhint-disable-next-line
if (s.getLastUpdatedOnInternal(coverKey) + _getUpdateInterval(s) > block.timestamp) {
return;
}
PriceLibV1.setNpmPrice(s);
if (coverKey > 0) {
_updateWithdrawalPeriod(s, coverKey);
_invokeAssetManagement(s, coverKey);
s.setLastUpdatedOnInternal(coverKey);
}
}
function _getUpdateInterval(IStore s) private view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_LIQUIDITY_STATE_UPDATE_INTERVAL);
}
function getWithdrawalInfoInternal(IStore s, bytes32 coverKey)
public
view
returns (
bool isWithdrawalPeriod,
uint256 lendingPeriod,
uint256 withdrawalWindow,
uint256 start,
uint256 end
)
{
(lendingPeriod, withdrawalWindow) = s.getRiskPoolingPeriodsInternal(coverKey);
// Get the withdrawal period of this cover liquidity
start = s.getUintByKey(getNextWithdrawalStartKeyInternal(coverKey));
end = s.getUintByKey(getNextWithdrawalEndKeyInternal(coverKey));
// solhint-disable-next-line
if (block.timestamp >= start && block.timestamp <= end) {
isWithdrawalPeriod = true;
}
}
function _isWithdrawalPeriod(IStore s, bytes32 coverKey) private view returns (bool) {
(bool isWithdrawalPeriod, , , , ) = getWithdrawalInfoInternal(s, coverKey);
return isWithdrawalPeriod;
}
function _updateWithdrawalPeriod(IStore s, bytes32 coverKey) private {
(, uint256 lendingPeriod, uint256 withdrawalWindow, uint256 start, uint256 end) = getWithdrawalInfoInternal(s, coverKey);
// Without a lending period and withdrawal window, nothing can be updated
if (lendingPeriod == 0 || withdrawalWindow == 0) {
return;
}
// The withdrawal period is now over.
// Deposits can be performed again.
// Set the next withdrawal cycle
if (block.timestamp > end) {
// solhint-disable-previous-line
// Next Withdrawal Cycle
// Withdrawals can start after the lending period
start = block.timestamp + lendingPeriod; // solhint-disable
// Withdrawals can be performed until the end of the next withdrawal cycle
end = start + withdrawalWindow;
s.setUintByKey(getNextWithdrawalStartKeyInternal(coverKey), start);
s.setUintByKey(getNextWithdrawalEndKeyInternal(coverKey), end);
setAccrualCompleteInternal(s, coverKey, false);
}
}
function isAccrualCompleteInternal(IStore s, bytes32 coverKey) external view returns (bool) {
return s.getBoolByKey(getAccrualInvocationKeyInternal(coverKey));
}
function setAccrualCompleteInternal(
IStore s,
bytes32 coverKey,
bool flag
) public {
s.setBoolByKey(getAccrualInvocationKeyInternal(coverKey), flag);
}
/**
* @dev Hash key of the "accrual invocation status" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getAccrualInvocationKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_ACCRUAL_INVOCATION, coverKey));
}
/**
* @dev Hash key of the "next withdrawal start date" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getNextWithdrawalStartKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_WITHDRAWAL_START, coverKey));
}
/**
* @dev Hash key of the "next withdrawal end date" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getNextWithdrawalEndKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_WITHDRAWAL_END, coverKey));
}
function mustBeDuringWithdrawalPeriod(IStore s, bytes32 coverKey) external view {
// Get the withdrawal period of this cover liquidity
uint256 start = s.getUintByKey(getNextWithdrawalStartKeyInternal(coverKey));
uint256 end = s.getUintByKey(getNextWithdrawalEndKeyInternal(coverKey));
require(start > 0 && block.timestamp >= start, "Withdrawal period has not started");
require(end > 0 && block.timestamp <= end, "Withdrawal period has already ended");
}
function _executeAndGetAction(
IStore s,
ILendingStrategy,
bytes32 coverKey
) private returns (Action) {
// If the cover is undergoing reporting, withdraw everything
bool isNormal = s.isCoverNormalInternal(coverKey);
if (isNormal != true) {
// Reset the withdrawal window
s.setUintByKey(getNextWithdrawalStartKeyInternal(coverKey), 0);
s.setUintByKey(getNextWithdrawalEndKeyInternal(coverKey), 0);
return Action.Withdraw;
}
if (_isWithdrawalPeriod(s, coverKey) == true) {
return Action.Withdraw;
}
return Action.Deposit;
}
function _canDeposit(
IStore s,
ILendingStrategy strategy,
uint256 totalStrategies,
bytes32 coverKey
) private view returns (uint256) {
IERC20 stablecoin = IERC20(s.getStablecoinAddressInternal());
uint256 totalBalance = s.getStablecoinOwnedByVaultInternal(coverKey);
uint256 maximumAllowed = (totalBalance * s.getMaxLendingRatioInternal()) / ProtoUtilV1.MULTIPLIER;
uint256 allocation = maximumAllowed / totalStrategies;
uint256 weight = strategy.getWeight();
uint256 canDeposit = (allocation * weight) / ProtoUtilV1.MULTIPLIER;
uint256 alreadyDeposited = s.getAmountInStrategyInternal(coverKey, strategy.getName(), address(stablecoin));
if (alreadyDeposited >= canDeposit) {
return 0;
}
return canDeposit - alreadyDeposited;
}
function _invokeAssetManagement(IStore s, bytes32 coverKey) private {
address vault = s.getVaultAddress(coverKey);
_withdrawFromDisabled(s, coverKey, vault);
address[] memory strategies = s.getActiveStrategiesInternal();
for (uint256 i = 0; i < strategies.length; i++) {
ILendingStrategy strategy = ILendingStrategy(strategies[i]);
_executeStrategy(s, strategy, strategies.length, vault, coverKey);
}
}
function _executeStrategy(
IStore s,
ILendingStrategy strategy,
uint256 totalStrategies,
address vault,
bytes32 coverKey
) private {
uint256 canDeposit = _canDeposit(s, strategy, totalStrategies, coverKey);
uint256 balance = IERC20(s.getStablecoinAddressInternal()).balanceOf(vault);
if (canDeposit > balance) {
canDeposit = balance;
}
Action action = _executeAndGetAction(s, strategy, coverKey);
if (action == Action.Deposit && canDeposit == 0) {
return;
}
if (action == Action.Withdraw) {
_withdrawAllFromStrategy(strategy, vault, coverKey);
return;
}
_depositToStrategy(strategy, coverKey, canDeposit);
}
function _depositToStrategy(
ILendingStrategy strategy,
bytes32 coverKey,
uint256 amount
) private {
strategy.deposit(coverKey, amount);
}
function _withdrawAllFromStrategy(
ILendingStrategy strategy,
address vault,
bytes32 coverKey
) private returns (uint256 stablecoinWithdrawn) {
uint256 balance = IERC20(strategy.getDepositCertificate()).balanceOf(vault);
if (balance > 0) {
stablecoinWithdrawn = strategy.withdraw(coverKey);
}
}
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 = IERC20(strategy.getDepositCertificate()).balanceOf(onBehalfOf);
if (balance > 0) {
strategy.withdraw(coverKey);
}
}
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "./IMember.sol";
pragma solidity ^0.8.0;
interface ILendingStrategy is IMember {
struct LendingStrategyInfoType {
uint256 deposits;
uint256 withdrawals;
}
event LogDeposit(bytes32 indexed name, uint256 counter, uint256 amount, uint256 certificateReceived, uint256 depositTotal, uint256 withdrawalTotal);
event Deposited(bytes32 indexed key, address indexed onBehalfOf, uint256 stablecoinDeposited, uint256 certificateTokenIssued);
event LogWithdrawal(bytes32 indexed name, uint256 counter, uint256 stablecoinWithdrawn, uint256 certificateRedeemed, uint256 depositTotal, uint256 withdrawalTotal);
event Withdrawn(bytes32 indexed key, address indexed sendTo, uint256 stablecoinWithdrawn, uint256 certificateTokenRedeemed);
event Drained(IERC20 indexed asset, uint256 amount);
function getKey() external pure returns (bytes32);
function getWeight() external pure returns (uint256);
function getDepositAsset() external view returns (IERC20);
function getDepositCertificate() external view returns (IERC20);
/**
* @dev Gets info of this strategy by cover key
* @param coverKey Enter the cover key
*/
function getInfo(bytes32 coverKey) external view returns (LendingStrategyInfoType memory info);
function deposit(bytes32 coverKey, uint256 amount) external returns (uint256 certificateReceived);
function withdraw(bytes32 coverKey) external returns (uint256 stablecoinWithdrawn);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IStore.sol";
import "../interfaces/IPriceOracle.sol";
import "../dependencies/uniswap-v2/IUniswapV2RouterLike.sol";
import "../dependencies/uniswap-v2/IUniswapV2PairLike.sol";
import "../dependencies/uniswap-v2/IUniswapV2FactoryLike.sol";
import "./ProtoUtilV1.sol";
library PriceLibV1 {
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
function getPriceOracleInternal(IStore s) public view returns (IPriceOracle) {
return IPriceOracle(s.getNpmPriceOracleInternal());
}
function setNpmPrice(IStore s) internal {
IPriceOracle oracle = getPriceOracleInternal(s);
if (address(oracle) == address(0)) {
return;
}
oracle.update();
}
function convertNpmLpUnitsToStabelcoinInternal(IStore s, uint256 amountIn) external view returns (uint256) {
return getPriceOracleInternal(s).consultPair(amountIn);
}
function getLastUpdatedOnInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
bytes32 key = getLastUpdateKeyInternal(coverKey);
return s.getUintByKey(key);
}
function setLastUpdatedOnInternal(IStore s, bytes32 coverKey) external {
bytes32 key = getLastUpdateKeyInternal(coverKey);
s.setUintByKey(key, block.timestamp); // solhint-disable-line
}
/**
* @dev Hash key of the "last state update" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getLastUpdateKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LAST_LIQUIDITY_STATE_UPDATE, coverKey));
}
function getNpmPriceInternal(IStore s, uint256 amountIn) external view returns (uint256) {
return getPriceOracleInternal(s).consult(s.getNpmTokenAddressInternal(), amountIn);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../dependencies/BokkyPooBahsDateTimeLibrary.sol";
import "../interfaces/IStore.sol";
import "../interfaces/ICxToken.sol";
import "../interfaces/IERC20Detailed.sol";
import "./StrategyLibV1.sol";
library CoverUtilV1 {
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
using StrategyLibV1 for IStore;
uint256 public constant REASSURANCE_WEIGHT_FALLBACK_VALUE = 8000;
uint256 public constant COVER_LAG_FALLBACK_VALUE = 1 days;
enum ProductStatus {
Normal,
Stopped,
IncidentHappened,
FalseReporting,
Claimable
}
/**
* @dev Returns the given cover's owner.
*
* Warning: this function does not validate the cover key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
*
*/
function getCoverOwnerInternal(IStore s, bytes32 coverKey) external view returns (address) {
return s.getAddressByKeys(ProtoUtilV1.NS_COVER_OWNER, coverKey);
}
/**
* @dev Returns cover creation fee information.
* @param s Specify store instance
*
* @return fee Returns the amount of NPM tokens you need to pay to create a new cover
* @return minCoverCreationStake Returns the amount of NPM tokens you need to stake to create a new cover
* @return minStakeToAddLiquidity Returns the amount of NPM tokens you need to stake to add liquidity
*
*/
function getCoverCreationFeeInfoInternal(IStore s)
external
view
returns (
uint256 fee,
uint256 minCoverCreationStake,
uint256 minStakeToAddLiquidity
)
{
fee = s.getUintByKey(ProtoUtilV1.NS_COVER_CREATION_FEE);
minCoverCreationStake = getMinCoverCreationStakeInternal(s);
minStakeToAddLiquidity = getMinStakeToAddLiquidityInternal(s);
}
/**
* @dev Returns minimum NPM stake to create a new cover.
* @param s Specify store instance
*/
function getMinCoverCreationStakeInternal(IStore s) public view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_COVER_CREATION_MIN_STAKE);
}
/**
* @dev Returns a cover's creation date
*
* Warning: this function does not validate the cover key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
*
*/
function getCoverCreationDateInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
return s.getUintByKeys(ProtoUtilV1.NS_COVER_CREATION_DATE, coverKey);
}
/**
* @dev Returns minimum NPM stake to add liquidity.
* @param s Specify store instance
*/
function getMinStakeToAddLiquidityInternal(IStore s) public view returns (uint256) {
return s.getUintByKey(ProtoUtilV1.NS_COVER_LIQUIDITY_MIN_STAKE);
}
/**
* @dev Gets claim period/duration of the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
*
*/
function getClaimPeriodInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
uint256 fromKey = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_PERIOD, coverKey);
uint256 fallbackValue = s.getUintByKey(ProtoUtilV1.NS_CLAIM_PERIOD);
return fromKey > 0 ? fromKey : fallbackValue;
}
/**
* @dev Returns a summary of the given cover pool.
*
* Warning: this function does not validate the cover key supplied.
*
*/
function getCoverPoolSummaryInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (IPolicy.CoverPoolSummaryType memory summary) {
uint256 precision = s.getStablecoinPrecisionInternal();
summary.totalAmountInPool = s.getStablecoinOwnedByVaultInternal(coverKey); // precision: stablecoin
summary.totalCommitment = getActiveLiquidityUnderProtectionInternal(s, coverKey, productKey, precision); // <-- adjusted precision
summary.reassuranceAmount = getReassuranceAmountInternal(s, coverKey); // precision: stablecoin
summary.reassurancePoolWeight = getReassuranceWeightInternal(s, coverKey);
summary.productCount = s.countBytes32ArrayByKeys(ProtoUtilV1.NS_COVER_PRODUCT, coverKey);
summary.leverage = s.getUintByKeys(ProtoUtilV1.NS_COVER_LEVERAGE_FACTOR, coverKey);
summary.productCapitalEfficiency = s.getUintByKeys(ProtoUtilV1.NS_COVER_PRODUCT_EFFICIENCY, coverKey, productKey);
}
/**
* @dev Gets the reassurance weight of a given cover key.
*
* Warning: this function does not validate the cover key supplied.
*
* @param s Provide store instance
* @param coverKey Enter the cover for which you want to obtain the reassurance weight for.
*
* @return If reassurance weight value wasn't set for the specified cover pool,
* the global value will be returned.
*
* If global value, too, isn't available, a fallback value of `REASSURANCE_WEIGHT_FALLBACK_VALUE`
* is returned.
*
*/
function getReassuranceWeightInternal(IStore s, bytes32 coverKey) public view returns (uint256) {
uint256 setForTheCoverPool = s.getUintByKey(getReassuranceWeightKeyInternal(coverKey));
if (setForTheCoverPool > 0) {
return setForTheCoverPool;
}
// Globally set value: not set for any specific cover
uint256 setGlobally = s.getUintByKey(getReassuranceWeightKeyInternal(0));
if (setGlobally > 0) {
return setGlobally;
}
return REASSURANCE_WEIGHT_FALLBACK_VALUE;
}
/**
* @dev Gets the reassurance amount of the specified cover contract
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter the cover key
*
*/
function getReassuranceAmountInternal(IStore s, bytes32 coverKey) public view returns (uint256) {
return s.getUintByKey(getReassuranceKeyInternal(coverKey));
}
/**
* @dev Returns reassurance rate of the specified cover key.
* When a cover is finalized after claims payout, a portion
* of the reassurance fund (if available) is transferred to the cover liquidity pool.
*
* If the reassurance rate is 25%, either 25% of the reassurance pool
* or 25% of the suffered loss is transferred prior to finalization, whichever is less.
*
* Warning: this function does not validate the cover key supplied.
*
* @param s Specify store
* @param coverKey Enter cover key
*
*/
function getReassuranceRateInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
uint256 rate = s.getUintByKey(getReassuranceRateKeyInternal(coverKey));
if (rate > 0) {
return rate;
}
// Default: 25%
return 2500;
}
/**
* @dev Hash key of the reassurance for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getReassuranceKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_REASSURANCE, coverKey));
}
/**
* @dev Hash key of the reassurance rate for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getReassuranceRateKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_REASSURANCE_RATE, coverKey));
}
/**
* @dev Hash key of the reassurance weight for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getReassuranceWeightKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_REASSURANCE_WEIGHT, coverKey));
}
/**
* @dev Indicates whether the specified cover and all associated products are "normal".
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @return Returns false if any associated product isn't normal.
*
*/
function isCoverNormalInternal(IStore s, bytes32 coverKey) external view returns (bool) {
uint256 incidentDate;
bool supportsProducts = supportsProductsInternal(s, coverKey);
if (supportsProducts == false) {
incidentDate = getActiveIncidentDateInternal(s, coverKey, ProtoUtilV1.PRODUCT_KEY_INTENTIONALLY_EMPTY);
return getProductStatusOfInternal(s, coverKey, ProtoUtilV1.PRODUCT_KEY_INTENTIONALLY_EMPTY, incidentDate) == ProductStatus.Normal;
}
bytes32[] memory products = _getProducts(s, coverKey);
for (uint256 i = 0; i < products.length; i++) {
incidentDate = getActiveIncidentDateInternal(s, coverKey, products[i]);
bool isNormal = getProductStatusOfInternal(s, coverKey, products[i], incidentDate) == ProductStatus.Normal;
if (!isNormal) {
return false;
}
}
return true;
}
/**
* @dev Gets product status of the given cover product.
*
*
* 0 - normal
* 1 - stopped, can not purchase covers or add liquidity
* 2 - reporting, incident happened
* 3 - reporting, false reporting
* 4 - claimable, claims accepted for payout
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getProductStatusInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view returns (ProductStatus) {
uint256 incidentDate = getActiveIncidentDateInternal(s, coverKey, productKey);
return getProductStatusOfInternal(s, coverKey, productKey, incidentDate);
}
/**
* @dev Returns current status a given cover product as `ProductStatus`.
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getProductStatusOfInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public view returns (ProductStatus) {
uint256 value = s.getUintByKey(getProductStatusOfKeyInternal(coverKey, productKey, incidentDate));
return ProductStatus(value);
}
/**
* @dev Hash key of the product status of (the given cover, product, and incident date)
* for historical significance. This must not be reset during finalization.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter incident date
*
*/
function getProductStatusOfKeyInternal(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_STATUS, coverKey, productKey, incidentDate));
}
/**
* @dev Hash key of the stakes (collectively added by liquidity providers) of the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getCoverLiquidityStakeKeyInternal(bytes32 coverKey) external pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_STAKE, coverKey));
}
/**
* @dev Hash key of the last stablecoin deposit of the given cover.
* There must be a couple of block heights as an offset
* before withdrawal can be performed (even during a withdrawal window).
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getLastDepositHeightKeyInternal(bytes32 coverKey) external pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_DEPOSIT_HEIGHTS, coverKey));
}
/**
* @dev Hash key of the individual stake (added by an LP) for the given cover and account.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param account Enter the account to obtain the hash key
*
*/
function getCoverLiquidityStakeIndividualKeyInternal(bytes32 coverKey, address account) external pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_STAKE, coverKey, account));
}
/**
* @dev Hash key of the blacklisted accounts for the given cover.
* Blacklisted accounts are forbidden to receive claims payout.
*
* Warning: this function does not validate the input arguments.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param incidentDate Enter the trigger incident date
*
*/
function getBlacklistKeyInternal(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_CLAIM_BLACKLIST, coverKey, productKey, incidentDate));
}
/**
* @dev Returns the total liquidity committed/under active protection.
* If the cover is a diversified pool, returns sum total of all products' commitments.
*
* Simply put, commitments are the "totalSupply" of cxTokens that haven't yet expired.
* Note that cxTokens can be precise to 18 decimal places.
* If the protocol's stablecoin has a different precision,
* you must tell this function explicitly when you call it.
*
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param precision Specify the protocol stablecoin precision.
*
*/
function getTotalLiquidityUnderProtectionInternal(
IStore s,
bytes32 coverKey,
uint256 precision
) external view returns (uint256 total) {
bool supportsProducts = supportsProductsInternal(s, coverKey);
if (supportsProducts == false) {
return getActiveLiquidityUnderProtectionInternal(s, coverKey, ProtoUtilV1.PRODUCT_KEY_INTENTIONALLY_EMPTY, precision);
}
bytes32[] memory products = _getProducts(s, coverKey);
for (uint256 i = 0; i < products.length; i++) {
total += getActiveLiquidityUnderProtectionInternal(s, coverKey, products[i], precision);
}
}
function _getProducts(IStore s, bytes32 coverKey) private view returns (bytes32[] memory products) {
return s.getBytes32ArrayByKeys(ProtoUtilV1.NS_COVER_PRODUCT, coverKey);
}
/**
* @dev Returns the total liquidity committed/under active protection.
* If the cover is a diversified pool, you must a provide product key.
*
* Simply put, commitments are the "totalSupply" of cxTokens that haven't yet expired.
* Note that cxTokens are precise to 18 decimal places.
* If the protocol's stablecoin has a different precision,
* you must tell this function explicitly when you call it.
*
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param adjustPrecision Specify the protocol stablecoin precision.
*
*/
function getActiveLiquidityUnderProtectionInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 adjustPrecision
) public view returns (uint256 total) {
(uint256 current, uint256 expiryDate) = _getCurrentCommitment(s, coverKey, productKey);
uint256 future = _getFutureCommitments(s, coverKey, productKey, expiryDate);
total = current + future;
// @caution:
// Adjusting precision results in truncation and data loss.
//
// Can also open a can of worms if the protocol stablecoin
// address needs to be updated in the future.
total = (total * adjustPrecision) / ProtoUtilV1.CXTOKEN_PRECISION;
}
/**
* @dev Gets current commitment of a given cover product.
*
* <br /> <br />
*
* If there is no incident, should return zero.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*
* @return amount The current commitment amount.
* @return expiryDate The time at which the commitment `amount` expires.
*
*/
function _getCurrentCommitment(
IStore s,
bytes32 coverKey,
bytes32 productKey
) private view returns (uint256 amount, uint256 expiryDate) {
uint256 incidentDateIfAny = getActiveIncidentDateInternal(s, coverKey, productKey);
// There isn't any incident for this cover
// and therefore no need to pay
if (incidentDateIfAny == 0) {
return (0, 0);
}
expiryDate = _getMonthEndDate(incidentDateIfAny);
ICxToken cxToken = ICxToken(getCxTokenByExpiryDateInternal(s, coverKey, productKey, expiryDate));
if (address(cxToken) != address(0)) {
amount = cxToken.totalSupply();
}
}
/**
* @dev Gets future commitment of a given cover product.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param excludedExpiryDate Enter expiry date (from current commitment) to exclude
*
* @return sum The total commitment amount.
*
*/
function _getFutureCommitments(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 excludedExpiryDate
) private view returns (uint256 sum) {
for (uint256 i = 0; i <= ProtoUtilV1.MAX_POLICY_DURATION; i++) {
uint256 expiryDate = _getNextMonthEndDate(block.timestamp, i); // solhint-disable-line
if (expiryDate == excludedExpiryDate || expiryDate <= block.timestamp) {
// solhint-disable-previous-line
continue;
}
ICxToken cxToken = ICxToken(getCxTokenByExpiryDateInternal(s, coverKey, productKey, expiryDate));
if (address(cxToken) != address(0)) {
sum += cxToken.totalSupply();
}
}
}
/**
* @dev Sets the current status of a given cover
*
* 0 - normal
* 1 - stopped, can not purchase covers or add liquidity
* 2 - reporting, incident happened
* 3 - reporting, false reporting
* 4 - claimable, claims accepted for payout
*
*/
function setStatusInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
ProductStatus status
) external {
s.setUintByKey(getProductStatusOfKeyInternal(coverKey, productKey, incidentDate), uint256(status));
}
/**
* @dev Gets the expiry date based on cover duration
* @param today Enter the current timestamp
* @param coverDuration Enter the number of months to cover. Accepted values: 1-3.
*/
function getExpiryDateInternal(uint256 today, uint256 coverDuration) external pure returns (uint256) {
// Get the day of the month
(, , uint256 day) = BokkyPooBahsDateTimeLibrary.timestampToDate(today);
// Cover duration of 1 month means current month
// unless today is the 25th calendar day or later
uint256 monthToAdd = coverDuration - 1;
if (day >= 25) {
// Add one month
monthToAdd += 1;
}
return _getNextMonthEndDate(today, monthToAdd);
}
// function _getPreviousMonthEndDate(uint256 date, uint256 monthsToSubtract) private pure returns (uint256) {
// uint256 pastDate = BokkyPooBahsDateTimeLibrary.subMonths(date, monthsToSubtract);
// return _getMonthEndDate(pastDate);
// }
function _getNextMonthEndDate(uint256 date, uint256 monthsToAdd) private pure returns (uint256) {
uint256 futureDate = BokkyPooBahsDateTimeLibrary.addMonths(date, monthsToAdd);
return _getMonthEndDate(futureDate);
}
function _getMonthEndDate(uint256 date) private pure returns (uint256) {
// Get the year and month from the date
(uint256 year, uint256 month, ) = BokkyPooBahsDateTimeLibrary.timestampToDate(date);
// Count the total number of days of that month and year
uint256 daysInMonth = BokkyPooBahsDateTimeLibrary._getDaysInMonth(year, month);
// Get the month end date
return BokkyPooBahsDateTimeLibrary.timestampFromDateTime(year, month, daysInMonth, 23, 59, 59);
}
/**
* @dev Returns the given cover product's cxToken by its expiry date (if available).
*
* Warning: this function does not validate the input arguments.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
* @param expiryDate Enter cxToken's expiry date
*
*/
function getCxTokenByExpiryDateInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
uint256 expiryDate
) public view returns (address cxToken) {
bytes32 k = keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_CXTOKEN, coverKey, productKey, expiryDate));
cxToken = s.getAddress(k);
}
function checkIfProductRequiresWhitelistInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (bool) {
return s.getBoolByKeys(ProtoUtilV1.NS_COVER_REQUIRES_WHITELIST, coverKey, productKey);
}
function checkIfRequiresWhitelistInternal(IStore s, bytes32 coverKey) external view returns (bool) {
return s.getBoolByKeys(ProtoUtilV1.NS_COVER_REQUIRES_WHITELIST, coverKey);
}
function supportsProductsInternal(IStore s, bytes32 coverKey) public view returns (bool) {
return s.getBoolByKeys(ProtoUtilV1.NS_COVER_SUPPORTS_PRODUCTS, coverKey);
}
function isValidProductInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (bool) {
return s.getBoolByKeys(ProtoUtilV1.NS_COVER_PRODUCT, coverKey, productKey);
}
function isActiveProductInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (bool) {
return s.getUintByKeys(ProtoUtilV1.NS_COVER_PRODUCT, coverKey, productKey) == 1;
}
function disablePolicyInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey,
bool status
) external {
bytes32 key = getPolicyDisabledKeyInternal(coverKey, productKey);
s.setBoolByKey(key, status);
}
function isPolicyDisabledInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) external view returns (bool) {
bytes32 key = getPolicyDisabledKeyInternal(coverKey, productKey);
return s.getBoolByKey(key);
}
/**
* @dev Hash key of the "disabled policy flag" for the given cover product.
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param coverKey Enter cover key
* @param productKey Enter product key
*
*/
function getPolicyDisabledKeyInternal(bytes32 coverKey, bytes32 productKey) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_POLICY_DISABLED, coverKey, productKey));
}
/**
* @dev Gets the latest and "active" incident date of a cover product.
* Note that after "resolve" is invoked, incident date is reset.
*
* Warning: this function does not validate the cover and product key supplied.
*
* @param s Specify store instance
* @param coverKey Enter cover key
* @param productKey Enter product key
*/
function getActiveIncidentDateInternal(
IStore s,
bytes32 coverKey,
bytes32 productKey
) public view returns (uint256) {
return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_INCIDENT_DATE, coverKey, productKey);
}
function getCoverageLagInternal(IStore s, bytes32 coverKey) internal view returns (uint256) {
uint256 custom = s.getUintByKeys(ProtoUtilV1.NS_COVERAGE_LAG, coverKey);
// Custom means set for this exact cover
if (custom > 0) {
return custom;
}
// Global means set for all covers (without specifying a cover key)
uint256 global = s.getUintByKey(ProtoUtilV1.NS_COVERAGE_LAG);
if (global > 0) {
return global;
}
// Fallback means the default option
return COVER_LAG_FALLBACK_VALUE;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IPriceOracle {
function update() external;
function consult(address token, uint256 amountIn) external view returns (uint256 amountOut);
function consultPair(uint256 amountIn) external view returns (uint256);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IUniswapV2RouterLike {
function factory() external view returns (address);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IUniswapV2PairLike {
function token0() external view returns (address);
function token1() external view returns (address);
function totalSupply() external view returns (uint256);
function getReserves()
external
view
returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IUniswapV2FactoryLike {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "./StoreKeyUtil.sol";
import "../interfaces/IStore.sol";
import "../interfaces/IProtocol.sol";
import "../interfaces/IERC20Detailed.sol";
library ProtoUtilV1 {
using StoreKeyUtil for IStore;
// Magic numbers
uint256 public constant MAX_POLICY_DURATION = 3;
bytes32 public constant KEY_INTENTIONALLY_EMPTY = 0;
bytes32 public constant PRODUCT_KEY_INTENTIONALLY_EMPTY = 0;
uint256 public constant MULTIPLIER = 10_000;
uint256 public constant MIN_LIQUIDITY = 10;
uint256 public constant MAX_LIQUIDITY = 10_000_000;
uint256 public constant MIN_PROPOSAL_AMOUNT = 10;
uint256 public constant MAX_PROPOSAL_AMOUNT = 10_000_000;
uint256 public constant MAX_NPM_STAKE = 10_000_000;
uint256 public constant NPM_PRECISION = 1 ether;
uint256 public constant CXTOKEN_PRECISION = 1 ether;
uint256 public constant POD_PRECISION = 1 ether;
/// @dev Protocol contract namespace
bytes32 public constant CNS_CORE = "cns:core";
/// @dev The address of NPM token available in this blockchain
bytes32 public constant CNS_NPM = "cns:core:npm:instance";
/// @dev Key prefix for creating a new cover product on chain
bytes32 public constant CNS_COVER = "cns:cover";
bytes32 public constant CNS_UNISWAP_V2_ROUTER = "cns:core:uni:v2:router";
bytes32 public constant CNS_UNISWAP_V2_FACTORY = "cns:core:uni:v2:factory";
bytes32 public constant CNS_PRICE_DISCOVERY = "cns:core:price:discovery";
bytes32 public constant CNS_TREASURY = "cns:core:treasury";
bytes32 public constant CNS_NPM_PRICE_ORACLE = "cns:core:npm:price:oracle";
bytes32 public constant CNS_COVER_REASSURANCE = "cns:cover:reassurance";
bytes32 public constant CNS_POOL_BOND = "cns:pool:bond";
bytes32 public constant CNS_COVER_POLICY = "cns:cover:policy";
bytes32 public constant CNS_COVER_POLICY_MANAGER = "cns:cover:policy:manager";
bytes32 public constant CNS_COVER_POLICY_ADMIN = "cns:cover:policy:admin";
bytes32 public constant CNS_COVER_STAKE = "cns:cover:stake";
bytes32 public constant CNS_COVER_VAULT = "cns:cover:vault";
bytes32 public constant CNS_COVER_VAULT_DELEGATE = "cns:cover:vault:delegate";
bytes32 public constant CNS_COVER_STABLECOIN = "cns:cover:sc";
bytes32 public constant CNS_COVER_CXTOKEN_FACTORY = "cns:cover:cxtoken:factory";
bytes32 public constant CNS_COVER_VAULT_FACTORY = "cns:cover:vault:factory";
bytes32 public constant CNS_BOND_POOL = "cns:pools:bond";
bytes32 public constant CNS_STAKING_POOL = "cns:pools:staking";
bytes32 public constant CNS_LIQUIDITY_ENGINE = "cns:liquidity:engine";
bytes32 public constant CNS_STRATEGY_AAVE = "cns:strategy:aave";
bytes32 public constant CNS_STRATEGY_COMPOUND = "cns:strategy:compound";
/// @dev Governance contract address
bytes32 public constant CNS_GOVERNANCE = "cns:gov";
/// @dev Governance:Resolution contract address
bytes32 public constant CNS_GOVERNANCE_RESOLUTION = "cns:gov:resolution";
/// @dev Claims processor contract address
bytes32 public constant CNS_CLAIM_PROCESSOR = "cns:claim:processor";
/// @dev The address where `burn tokens` are sent or collected.
/// The collection behavior (collection) is required if the protocol
/// is deployed on a sidechain or a layer-2 blockchain.
/// \n
/// The collected NPM tokens are will be periodically bridged back to Ethereum
/// and then burned.
bytes32 public constant CNS_BURNER = "cns:core:burner";
/// @dev Namespace for all protocol members.
bytes32 public constant NS_MEMBERS = "ns:members";
/// @dev Namespace for protocol contract members.
bytes32 public constant NS_CONTRACTS = "ns:contracts";
/// @dev Key prefix for creating a new cover product on chain
bytes32 public constant NS_COVER = "ns:cover";
bytes32 public constant NS_COVER_PRODUCT = "ns:cover:product";
bytes32 public constant NS_COVER_PRODUCT_EFFICIENCY = "ns:cover:product:efficiency";
bytes32 public constant NS_COVER_CREATION_DATE = "ns:cover:creation:date";
bytes32 public constant NS_COVER_CREATION_FEE = "ns:cover:creation:fee";
bytes32 public constant NS_COVER_CREATION_MIN_STAKE = "ns:cover:creation:min:stake";
bytes32 public constant NS_COVER_REASSURANCE = "ns:cover:reassurance";
bytes32 public constant NS_COVER_REASSURANCE_PAYOUT = "ns:cover:reassurance:payout";
bytes32 public constant NS_COVER_REASSURANCE_WEIGHT = "ns:cover:reassurance:weight";
bytes32 public constant NS_COVER_REASSURANCE_RATE = "ns:cover:reassurance:rate";
bytes32 public constant NS_COVER_LEVERAGE_FACTOR = "ns:cover:leverage:factor";
bytes32 public constant NS_COVER_CREATION_FEE_EARNING = "ns:cover:creation:fee:earning";
bytes32 public constant NS_COVER_INFO = "ns:cover:info";
bytes32 public constant NS_COVER_OWNER = "ns:cover:owner";
bytes32 public constant NS_COVER_SUPPORTS_PRODUCTS = "ns:cover:supports:products";
bytes32 public constant NS_VAULT_STRATEGY_OUT = "ns:vault:strategy:out";
bytes32 public constant NS_VAULT_LENDING_INCOMES = "ns:vault:lending:incomes";
bytes32 public constant NS_VAULT_LENDING_LOSSES = "ns:vault:lending:losses";
bytes32 public constant NS_VAULT_DEPOSIT_HEIGHTS = "ns:vault:deposit:heights";
bytes32 public constant NS_COVER_LIQUIDITY_LENDING_PERIOD = "ns:cover:liquidity:len:p";
bytes32 public constant NS_COVER_LIQUIDITY_MAX_LENDING_RATIO = "ns:cover:liquidity:max:lr";
bytes32 public constant NS_COVER_LIQUIDITY_WITHDRAWAL_WINDOW = "ns:cover:liquidity:ww";
bytes32 public constant NS_COVER_LIQUIDITY_MIN_STAKE = "ns:cover:liquidity:min:stake";
bytes32 public constant NS_COVER_LIQUIDITY_STAKE = "ns:cover:liquidity:stake";
bytes32 public constant NS_COVER_LIQUIDITY_COMMITTED = "ns:cover:liquidity:committed";
bytes32 public constant NS_COVER_STABLECOIN_NAME = "ns:cover:stablecoin:name";
bytes32 public constant NS_COVER_REQUIRES_WHITELIST = "ns:cover:requires:whitelist";
bytes32 public constant NS_COVER_HAS_FLASH_LOAN = "ns:cover:has:fl";
bytes32 public constant NS_COVER_LIQUIDITY_FLASH_LOAN_FEE = "ns:cover:liquidity:fl:fee";
bytes32 public constant NS_COVER_LIQUIDITY_FLASH_LOAN_FEE_PROTOCOL = "ns:proto:cover:liquidity:fl:fee";
bytes32 public constant NS_COVERAGE_LAG = "ns:coverage:lag";
bytes32 public constant NS_COVER_POLICY_RATE_FLOOR = "ns:cover:policy:rate:floor";
bytes32 public constant NS_COVER_POLICY_RATE_CEILING = "ns:cover:policy:rate:ceiling";
bytes32 public constant NS_POLICY_DISABLED = "ns:policy:disabled";
bytes32 public constant NS_POLICY_LAST_PURCHASE_ID = "ns:policy:last:purchase:id";
bytes32 public constant NS_COVER_STAKE = "ns:cover:stake";
bytes32 public constant NS_COVER_STAKE_OWNED = "ns:cover:stake:owned";
bytes32 public constant NS_COVER_STATUS = "ns:cover:status";
bytes32 public constant NS_COVER_CXTOKEN = "ns:cover:cxtoken";
bytes32 public constant NS_VAULT_TOKEN_NAME = "ns:vault:token:name";
bytes32 public constant NS_VAULT_TOKEN_SYMBOL = "ns:vault:token:symbol";
bytes32 public constant NS_COVER_CREATOR_WHITELIST = "ns:cover:creator:whitelist";
bytes32 public constant NS_COVER_USER_WHITELIST = "ns:cover:user:whitelist";
bytes32 public constant NS_COVER_CLAIM_BLACKLIST = "ns:cover:claim:blacklist";
/// @dev Resolution timestamp = timestamp of first reporting + reporting period
bytes32 public constant NS_GOVERNANCE_RESOLUTION_TS = "ns:gov:resolution:ts";
/// @dev The timestamp when a tokenholder withdraws their reporting stake
bytes32 public constant NS_GOVERNANCE_UNSTAKEN = "ns:gov:unstaken";
/// @dev The timestamp when a tokenholder withdraws their reporting stake
bytes32 public constant NS_GOVERNANCE_UNSTAKE_TS = "ns:gov:unstake:ts";
/// @dev The reward received by the winning camp
bytes32 public constant NS_GOVERNANCE_UNSTAKE_REWARD = "ns:gov:unstake:reward";
/// @dev The stakes burned during incident resolution
bytes32 public constant NS_GOVERNANCE_UNSTAKE_BURNED = "ns:gov:unstake:burned";
/// @dev The stakes burned during incident resolution
bytes32 public constant NS_GOVERNANCE_UNSTAKE_REPORTER_FEE = "ns:gov:unstake:rep:fee";
bytes32 public constant NS_GOVERNANCE_REPORTING_MIN_FIRST_STAKE = "ns:gov:rep:min:first:stake";
/// @dev An approximate date and time when trigger event or cover incident occurred
bytes32 public constant NS_GOVERNANCE_REPORTING_INCIDENT_DATE = "ns:gov:rep:incident:date";
/// @dev A period (in solidity timestamp) configurable by cover creators during
/// when NPM tokenholders can vote on incident reporting proposals
bytes32 public constant NS_GOVERNANCE_REPORTING_PERIOD = "ns:gov:rep:period";
/// @dev Used as key element in a couple of places:
/// 1. For uint256 --> Sum total of NPM witnesses who saw incident to have happened
/// 2. For address --> The address of the first reporter
bytes32 public constant NS_GOVERNANCE_REPORTING_WITNESS_YES = "ns:gov:rep:witness:yes";
/// @dev Used as key to flag if a cover was disputed. Cleared when a cover is finalized.
bytes32 public constant NS_GOVERNANCE_REPORTING_HAS_A_DISPUTE = "ns:gov:rep:has:dispute";
/// @dev Used as key to flag if a incident was finalized.
bytes32 public constant NS_GOVERNANCE_REPORTING_FINALIZATION = "ns:gov:rep:has:finalized";
/// @dev Used as key element in a couple of places:
/// 1. For uint256 --> Sum total of NPM witnesses who disagreed with and disputed an incident reporting
/// 2. For address --> The address of the first disputing reporter (disputer / candidate reporter)
bytes32 public constant NS_GOVERNANCE_REPORTING_WITNESS_NO = "ns:gov:rep:witness:no";
/// @dev Stakes guaranteed by an individual witness supporting the "incident happened" camp
bytes32 public constant NS_GOVERNANCE_REPORTING_STAKE_OWNED_YES = "ns:gov:rep:stake:owned:yes";
/// @dev Stakes guaranteed by an individual witness supporting the "false reporting" camp
bytes32 public constant NS_GOVERNANCE_REPORTING_STAKE_OWNED_NO = "ns:gov:rep:stake:owned:no";
/// @dev The percentage rate (x MULTIPLIER) of amount of reporting/unstake reward to burn.
/// @custom:note that the reward comes from the losing camp after resolution is achieved.
bytes32 public constant NS_GOVERNANCE_REPORTING_BURN_RATE = "ns:gov:rep:burn:rate";
/// @dev The percentage rate (x MULTIPLIER) of amount of reporting/unstake
/// reward to provide to the final reporter.
bytes32 public constant NS_GOVERNANCE_REPORTER_COMMISSION = "ns:gov:reporter:commission";
bytes32 public constant NS_CLAIM_PERIOD = "ns:claim:period";
bytes32 public constant NS_CLAIM_PAYOUTS = "ns:claim:payouts";
/// @dev A 24-hour delay after a governance agent "resolves" an actively reported cover.
bytes32 public constant NS_CLAIM_BEGIN_TS = "ns:claim:begin:ts";
/// @dev Claim expiry date = Claim begin date + claim duration
bytes32 public constant NS_CLAIM_EXPIRY_TS = "ns:claim:expiry:ts";
bytes32 public constant NS_RESOLUTION_DEADLINE = "ns:resolution:deadline";
/// @dev Claim expiry date = Claim begin date + claim duration
bytes32 public constant NS_RESOLUTION_COOL_DOWN_PERIOD = "ns:resolution:cdp";
/// @dev The percentage rate (x MULTIPLIER) of amount deducted by the platform
/// for each successful claims payout
bytes32 public constant NS_COVER_PLATFORM_FEE = "ns:cover:platform:fee";
/// @dev The percentage rate (x MULTIPLIER) of amount provided to the first reporter
/// upon favorable incident resolution. This amount is a commission of the
/// 'ns:claim:platform:fee'
bytes32 public constant NS_CLAIM_REPORTER_COMMISSION = "ns:claim:reporter:commission";
bytes32 public constant NS_LAST_LIQUIDITY_STATE_UPDATE = "ns:last:snl:update";
bytes32 public constant NS_LIQUIDITY_STATE_UPDATE_INTERVAL = "ns:snl:update:interval";
bytes32 public constant NS_LENDING_STRATEGY_ACTIVE = "ns:lending:strategy:active";
bytes32 public constant NS_LENDING_STRATEGY_DISABLED = "ns:lending:strategy:disabled";
bytes32 public constant NS_LENDING_STRATEGY_WITHDRAWAL_START = "ns:lending:strategy:w:start";
bytes32 public constant NS_ACCRUAL_INVOCATION = "ns:accrual:invocation";
bytes32 public constant NS_LENDING_STRATEGY_WITHDRAWAL_END = "ns:lending:strategy:w:end";
bytes32 public constant CNAME_PROTOCOL = "Neptune Mutual Protocol";
bytes32 public constant CNAME_TREASURY = "Treasury";
bytes32 public constant CNAME_POLICY = "Policy";
bytes32 public constant CNAME_POLICY_ADMIN = "Policy Admin";
bytes32 public constant CNAME_BOND_POOL = "BondPool";
bytes32 public constant CNAME_STAKING_POOL = "Staking Pool";
bytes32 public constant CNAME_CLAIMS_PROCESSOR = "Claims Processor";
bytes32 public constant CNAME_COVER = "Cover";
bytes32 public constant CNAME_GOVERNANCE = "Governance";
bytes32 public constant CNAME_RESOLUTION = "Resolution";
bytes32 public constant CNAME_VAULT_FACTORY = "Vault Factory";
bytes32 public constant CNAME_CXTOKEN_FACTORY = "cxToken Factory";
bytes32 public constant CNAME_COVER_STAKE = "Cover Stake";
bytes32 public constant CNAME_COVER_REASSURANCE = "Cover Reassurance";
bytes32 public constant CNAME_LIQUIDITY_VAULT = "Vault";
bytes32 public constant CNAME_VAULT_DELEGATE = "Vault Delegate";
bytes32 public constant CNAME_LIQUIDITY_ENGINE = "Liquidity Engine";
function getProtocolInternal(IStore s) external view returns (IProtocol) {
return IProtocol(getProtocolAddressInternal(s));
}
function getProtocolAddressInternal(IStore s) public view returns (address) {
return s.getAddressByKey(CNS_CORE);
}
function getContractInternal(
IStore s,
bytes32 name,
bytes32 key
) public view returns (address) {
if (key > 0) {
return s.getAddressByKeys(NS_CONTRACTS, name, key);
}
return s.getAddressByKeys(NS_CONTRACTS, name);
}
function isProtocolMemberInternal(IStore s, address contractAddress) public view returns (bool) {
return s.getBoolByKeys(ProtoUtilV1.NS_MEMBERS, contractAddress);
}
/**
* @dev Reverts if the caller is one of the protocol members.
*/
function mustBeProtocolMember(IStore s, address contractAddress) external view {
bool isMember = isProtocolMemberInternal(s, contractAddress);
require(isMember, "Not a protocol member");
}
/**
* @dev Ensures that the sender matches with the exact contract having the specified name.
* @param name Enter the name of the contract
* @param sender Enter the `msg.sender` value
*/
function mustBeExactContract(
IStore s,
bytes32 name,
bytes32 key,
address sender
) public view {
address contractAddress = getContractInternal(s, name, key);
require(sender == contractAddress, "Access denied");
}
/**
* @dev Ensures that the sender matches with the exact contract having the specified name.
* @param name Enter the name of the contract
*/
function senderMustBeExactContract(IStore s, bytes32 name) external view {
return callerMustBeExactContract(s, name, msg.sender);
}
/**
* @dev Ensures that the sender matches with the exact contract having the specified name.
* @param name Enter the name of the contract
*/
function callerMustBeExactContract(
IStore s,
bytes32 name,
address caller
) public view {
return mustBeExactContract(s, name, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY, caller);
}
function getNpmTokenInstanceInternal(IStore s) external view returns (IERC20) {
return IERC20(getNpmTokenAddressInternal(s));
}
function getNpmTokenAddressInternal(IStore s) public view returns (address) {
address npm = s.getAddressByKey(CNS_NPM);
return npm;
}
function getUniswapV2RouterInternal(IStore s) external view returns (address) {
return s.getAddressByKey(CNS_UNISWAP_V2_ROUTER);
}
function getUniswapV2FactoryInternal(IStore s) external view returns (address) {
return s.getAddressByKey(CNS_UNISWAP_V2_FACTORY);
}
function getNpmPriceOracleInternal(IStore s) external view returns (address) {
return s.getAddressByKey(CNS_NPM_PRICE_ORACLE);
}
function getTreasuryAddressInternal(IStore s) external view returns (address) {
return s.getAddressByKey(CNS_TREASURY);
}
function getStablecoinAddressInternal(IStore s) public view returns (address) {
return s.getAddressByKey(CNS_COVER_STABLECOIN);
}
function getStablecoinPrecisionInternal(IStore s) external view returns (uint256) {
return 10**IERC20Detailed(getStablecoinAddressInternal(s)).decimals();
}
function getBurnAddressInternal(IStore s) external view returns (address) {
return s.getAddressByKey(CNS_BURNER);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable func-order
pragma solidity ^0.8.0;
import "../interfaces/IStore.sol";
library StoreKeyUtil {
function setUintByKey(
IStore s,
bytes32 key,
uint256 value
) external {
require(key > 0, "Invalid key");
return s.setUint(key, value);
}
function setUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 value
) external {
return s.setUint(_getKey(key1, key2), value);
}
function setUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
uint256 value
) external {
return s.setUint(_getKey(key1, key2, key3), value);
}
function setUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account,
uint256 value
) external {
return s.setUint(_getKey(key1, key2, account), value);
}
function addUintByKey(
IStore s,
bytes32 key,
uint256 value
) external {
require(key > 0, "Invalid key");
return s.addUint(key, value);
}
function addUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 value
) external {
return s.addUint(_getKey(key1, key2), value);
}
function addUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account,
uint256 value
) external {
return s.addUint(_getKey(key1, key2, account), value);
}
function subtractUintByKey(
IStore s,
bytes32 key,
uint256 value
) external {
require(key > 0, "Invalid key");
return s.subtractUint(key, value);
}
function subtractUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 value
) external {
return s.subtractUint(_getKey(key1, key2), value);
}
function subtractUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account,
uint256 value
) external {
return s.subtractUint(_getKey(key1, key2, account), value);
}
function setStringByKey(
IStore s,
bytes32 key,
string calldata value
) external {
require(key > 0, "Invalid key");
s.setString(key, value);
}
function setStringByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
string calldata value
) external {
return s.setString(_getKey(key1, key2), value);
}
function setStringByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
string calldata value
) external {
return s.setString(_getKey(key1, key2, key3), value);
}
function setBytes32ByKey(
IStore s,
bytes32 key,
bytes32 value
) external {
require(key > 0, "Invalid key");
s.setBytes32(key, value);
}
function setBytes32ByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 value
) external {
return s.setBytes32(_getKey(key1, key2), value);
}
function setBytes32ByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
bytes32 value
) external {
return s.setBytes32(_getKey(key1, key2, key3), value);
}
function setBoolByKey(
IStore s,
bytes32 key,
bool value
) external {
require(key > 0, "Invalid key");
return s.setBool(key, value);
}
function setBoolByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bool value
) external {
return s.setBool(_getKey(key1, key2), value);
}
function setBoolByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
bool value
) external {
return s.setBool(_getKey(key1, key2, key3), value);
}
function setBoolByKeys(
IStore s,
bytes32 key,
address account,
bool value
) external {
return s.setBool(_getKey(key, account), value);
}
function setAddressByKey(
IStore s,
bytes32 key,
address value
) external {
require(key > 0, "Invalid key");
return s.setAddress(key, value);
}
function setAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address value
) external {
return s.setAddress(_getKey(key1, key2), value);
}
function setAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address value
) external {
return s.setAddress(_getKey(key1, key2, key3), value);
}
function setAddressArrayByKey(
IStore s,
bytes32 key,
address value
) external {
require(key > 0, "Invalid key");
return s.setAddressArrayItem(key, value);
}
function setAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address value
) external {
return s.setAddressArrayItem(_getKey(key1, key2), value);
}
function setAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address value
) external {
return s.setAddressArrayItem(_getKey(key1, key2, key3), value);
}
function setAddressBooleanByKey(
IStore s,
bytes32 key,
address account,
bool value
) external {
require(key > 0, "Invalid key");
return s.setAddressBoolean(key, account, value);
}
function setAddressBooleanByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account,
bool value
) external {
return s.setAddressBoolean(_getKey(key1, key2), account, value);
}
function setAddressBooleanByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address account,
bool value
) external {
return s.setAddressBoolean(_getKey(key1, key2, key3), account, value);
}
function deleteUintByKey(IStore s, bytes32 key) external {
require(key > 0, "Invalid key");
return s.deleteUint(key);
}
function deleteUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external {
return s.deleteUint(_getKey(key1, key2));
}
function deleteUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external {
return s.deleteUint(_getKey(key1, key2, key3));
}
function deleteBytes32ByKey(IStore s, bytes32 key) external {
require(key > 0, "Invalid key");
s.deleteBytes32(key);
}
function deleteBytes32ByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external {
return s.deleteBytes32(_getKey(key1, key2));
}
function deleteBoolByKey(IStore s, bytes32 key) external {
require(key > 0, "Invalid key");
return s.deleteBool(key);
}
function deleteBoolByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external {
return s.deleteBool(_getKey(key1, key2));
}
function deleteBoolByKeys(
IStore s,
bytes32 key,
address account
) external {
return s.deleteBool(_getKey(key, account));
}
function deleteAddressByKey(IStore s, bytes32 key) external {
require(key > 0, "Invalid key");
return s.deleteAddress(key);
}
function deleteAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external {
return s.deleteAddress(_getKey(key1, key2));
}
function deleteAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external {
return s.deleteAddress(_getKey(key1, key2, key3));
}
function deleteAddressArrayByKey(
IStore s,
bytes32 key,
address value
) external {
require(key > 0, "Invalid key");
return s.deleteAddressArrayItem(key, value);
}
function deleteAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address value
) external {
return s.deleteAddressArrayItem(_getKey(key1, key2), value);
}
function deleteAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address value
) external {
return s.deleteAddressArrayItem(_getKey(key1, key2, key3), value);
}
function deleteAddressArrayByIndexByKey(
IStore s,
bytes32 key,
uint256 index
) external {
require(key > 0, "Invalid key");
return s.deleteAddressArrayItemByIndex(key, index);
}
function deleteAddressArrayByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 index
) external {
return s.deleteAddressArrayItemByIndex(_getKey(key1, key2), index);
}
function deleteAddressArrayByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
uint256 index
) external {
return s.deleteAddressArrayItemByIndex(_getKey(key1, key2, key3), index);
}
function getUintByKey(IStore s, bytes32 key) external view returns (uint256) {
require(key > 0, "Invalid key");
return s.getUint(key);
}
function getUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (uint256) {
return s.getUint(_getKey(key1, key2));
}
function getUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (uint256) {
return s.getUint(_getKey(key1, key2, key3));
}
function getUintByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account
) external view returns (uint256) {
return s.getUint(_getKey(key1, key2, account));
}
function getStringByKey(IStore s, bytes32 key) external view returns (string memory) {
require(key > 0, "Invalid key");
return s.getString(key);
}
function getStringByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (string memory) {
return s.getString(_getKey(key1, key2));
}
function getBytes32ByKey(IStore s, bytes32 key) external view returns (bytes32) {
require(key > 0, "Invalid key");
return s.getBytes32(key);
}
function getBytes32ByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (bytes32) {
return s.getBytes32(_getKey(key1, key2));
}
function getBoolByKey(IStore s, bytes32 key) external view returns (bool) {
require(key > 0, "Invalid key");
return s.getBool(key);
}
function getBoolByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (bool) {
return s.getBool(_getKey(key1, key2, key3));
}
function getBoolByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (bool) {
return s.getBool(_getKey(key1, key2));
}
function getBoolByKeys(
IStore s,
bytes32 key,
address account
) external view returns (bool) {
return s.getBool(_getKey(key, account));
}
function getAddressByKey(IStore s, bytes32 key) external view returns (address) {
require(key > 0, "Invalid key");
return s.getAddress(key);
}
function getAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (address) {
return s.getAddress(_getKey(key1, key2));
}
function getAddressByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (address) {
return s.getAddress(_getKey(key1, key2, key3));
}
function getAddressBooleanByKey(
IStore s,
bytes32 key,
address account
) external view returns (bool) {
require(key > 0, "Invalid key");
return s.getAddressBoolean(key, account);
}
function getAddressBooleanByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address account
) external view returns (bool) {
return s.getAddressBoolean(_getKey(key1, key2), account);
}
function getAddressBooleanByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address account
) external view returns (bool) {
return s.getAddressBoolean(_getKey(key1, key2, key3), account);
}
function countAddressArrayByKey(IStore s, bytes32 key) external view returns (uint256) {
require(key > 0, "Invalid key");
return s.countAddressArrayItems(key);
}
function countAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (uint256) {
return s.countAddressArrayItems(_getKey(key1, key2));
}
function countAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (uint256) {
return s.countAddressArrayItems(_getKey(key1, key2, key3));
}
function getAddressArrayByKey(IStore s, bytes32 key) external view returns (address[] memory) {
require(key > 0, "Invalid key");
return s.getAddressArray(key);
}
function getAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (address[] memory) {
return s.getAddressArray(_getKey(key1, key2));
}
function getAddressArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (address[] memory) {
return s.getAddressArray(_getKey(key1, key2, key3));
}
function getAddressArrayItemPositionByKey(
IStore s,
bytes32 key,
address addressToFind
) external view returns (uint256) {
require(key > 0, "Invalid key");
return s.getAddressArrayItemPosition(key, addressToFind);
}
function getAddressArrayItemPositionByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
address addressToFind
) external view returns (uint256) {
return s.getAddressArrayItemPosition(_getKey(key1, key2), addressToFind);
}
function getAddressArrayItemPositionByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
address addressToFind
) external view returns (uint256) {
return s.getAddressArrayItemPosition(_getKey(key1, key2, key3), addressToFind);
}
function getAddressArrayItemByIndexByKey(
IStore s,
bytes32 key,
uint256 index
) external view returns (address) {
require(key > 0, "Invalid key");
return s.getAddressArrayItemByIndex(key, index);
}
function getAddressArrayItemByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 index
) external view returns (address) {
return s.getAddressArrayItemByIndex(_getKey(key1, key2), index);
}
function getAddressArrayItemByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
uint256 index
) external view returns (address) {
return s.getAddressArrayItemByIndex(_getKey(key1, key2, key3), index);
}
function _getKey(bytes32 key1, bytes32 key2) private pure returns (bytes32) {
return keccak256(abi.encodePacked(key1, key2));
}
function _getKey(
bytes32 key1,
bytes32 key2,
bytes32 key3
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(key1, key2, key3));
}
function _getKey(bytes32 key, address account) private pure returns (bytes32) {
return keccak256(abi.encodePacked(key, account));
}
function _getKey(
bytes32 key1,
bytes32 key2,
address account
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(key1, key2, account));
}
function setBytes32ArrayByKey(
IStore s,
bytes32 key,
bytes32 value
) external {
require(key > 0, "Invalid key");
return s.setBytes32ArrayItem(key, value);
}
function setBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 value
) external {
return s.setBytes32ArrayItem(_getKey(key1, key2), value);
}
function setBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
bytes32 value
) external {
return s.setBytes32ArrayItem(_getKey(key1, key2, key3), value);
}
function deleteBytes32ArrayByKey(
IStore s,
bytes32 key,
bytes32 value
) external {
require(key > 0, "Invalid key");
return s.deleteBytes32ArrayItem(key, value);
}
function deleteBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 value
) external {
return s.deleteBytes32ArrayItem(_getKey(key1, key2), value);
}
function deleteBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
bytes32 value
) external {
return s.deleteBytes32ArrayItem(_getKey(key1, key2, key3), value);
}
function deleteBytes32ArrayByIndexByKey(
IStore s,
bytes32 key,
uint256 index
) external {
require(key > 0, "Invalid key");
return s.deleteBytes32ArrayItemByIndex(key, index);
}
function deleteBytes32ArrayByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 index
) external {
return s.deleteBytes32ArrayItemByIndex(_getKey(key1, key2), index);
}
function deleteBytes32ArrayByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
uint256 index
) external {
return s.deleteBytes32ArrayItemByIndex(_getKey(key1, key2, key3), index);
}
function countBytes32ArrayByKey(IStore s, bytes32 key) external view returns (uint256) {
require(key > 0, "Invalid key");
return s.countBytes32ArrayItems(key);
}
function countBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (uint256) {
return s.countBytes32ArrayItems(_getKey(key1, key2));
}
function countBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (uint256) {
return s.countBytes32ArrayItems(_getKey(key1, key2, key3));
}
function getBytes32ArrayByKey(IStore s, bytes32 key) external view returns (bytes32[] memory) {
require(key > 0, "Invalid key");
return s.getBytes32Array(key);
}
function getBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2
) external view returns (bytes32[] memory) {
return s.getBytes32Array(_getKey(key1, key2));
}
function getBytes32ArrayByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3
) external view returns (bytes32[] memory) {
return s.getBytes32Array(_getKey(key1, key2, key3));
}
function getBytes32ArrayItemPositionByKey(
IStore s,
bytes32 key,
bytes32 bytes32ToFind
) external view returns (uint256) {
require(key > 0, "Invalid key");
return s.getBytes32ArrayItemPosition(key, bytes32ToFind);
}
function getBytes32ArrayItemPositionByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 bytes32ToFind
) external view returns (uint256) {
return s.getBytes32ArrayItemPosition(_getKey(key1, key2), bytes32ToFind);
}
function getBytes32ArrayItemPositionByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
bytes32 bytes32ToFind
) external view returns (uint256) {
return s.getBytes32ArrayItemPosition(_getKey(key1, key2, key3), bytes32ToFind);
}
function getBytes32ArrayItemByIndexByKey(
IStore s,
bytes32 key,
uint256 index
) external view returns (bytes32) {
require(key > 0, "Invalid key");
return s.getBytes32ArrayItemByIndex(key, index);
}
function getBytes32ArrayItemByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
uint256 index
) external view returns (bytes32) {
return s.getBytes32ArrayItemByIndex(_getKey(key1, key2), index);
}
function getBytes32ArrayItemByIndexByKeys(
IStore s,
bytes32 key1,
bytes32 key2,
bytes32 key3,
uint256 index
) external view returns (bytes32) {
return s.getBytes32ArrayItemByIndex(_getKey(key1, key2, key3), index);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
pragma solidity ^0.8.0;
interface IERC20Detailed is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function mint(uint256 amount) external;
}/* solhint-disable var-name-mixedcase, private-vars-leading-underscore, reason-string */
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ----------------------------------------------------------------------------
// BokkyPooBah's DateTime Library v1.01
//
// A gas-efficient Solidity date and time library
//
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary
//
// Tested date range 1970/01/01 to 2345/12/31
//
// Conventions:
// Unit | Range | Notes
// :-------- |:-------------:|:-----
// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC
// year | 1970 ... 2345 |
// month | 1 ... 12 |
// day | 1 ... 31 |
// hour | 0 ... 23 |
// minute | 0 ... 59 |
// second | 0 ... 59 |
// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday
//
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.
// ----------------------------------------------------------------------------
library BokkyPooBahsDateTimeLibrary {
uint256 internal constant SECONDS_PER_DAY = 24 * 60 * 60;
uint256 internal constant SECONDS_PER_HOUR = 60 * 60;
uint256 internal constant SECONDS_PER_MINUTE = 60;
int256 internal constant OFFSET19700101 = 2440588;
uint256 internal constant DOW_MON = 1;
uint256 internal constant DOW_TUE = 2;
uint256 internal constant DOW_WED = 3;
uint256 internal constant DOW_THU = 4;
uint256 internal constant DOW_FRI = 5;
uint256 internal constant DOW_SAT = 6;
uint256 internal constant DOW_SUN = 7;
// ------------------------------------------------------------------------
// Calculate the number of days from 1970/01/01 to year/month/day using
// the date conversion algorithm from
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php
// and subtracting the offset 2440588 so that 1970/01/01 is day 0
//
// days = day
// - 32075
// + 1461 * (year + 4800 + (month - 14) / 12) / 4
// + 367 * (month - 2 - (month - 14) / 12 * 12) / 12
// - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4
// - offset
// ------------------------------------------------------------------------
function _daysFromDate(
uint256 year,
uint256 month,
uint256 day
) internal pure returns (uint256 _days) {
require(year >= 1970);
int256 _year = int256(year);
int256 _month = int256(month);
int256 _day = int256(day);
int256 __days = _day -
32075 +
(1461 * (_year + 4800 + (_month - 14) / 12)) /
4 +
(367 * (_month - 2 - ((_month - 14) / 12) * 12)) /
12 -
(3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /
4 -
OFFSET19700101;
_days = uint256(__days);
}
// ------------------------------------------------------------------------
// Calculate year/month/day from the number of days since 1970/01/01 using
// the date conversion algorithm from
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php
// and adding the offset 2440588 so that 1970/01/01 is day 0
//
// int L = days + 68569 + offset
// int N = 4 * L / 146097
// L = L - (146097 * N + 3) / 4
// year = 4000 * (L + 1) / 1461001
// L = L - 1461 * year / 4 + 31
// month = 80 * L / 2447
// dd = L - 2447 * month / 80
// L = month / 11
// month = month + 2 - 12 * L
// year = 100 * (N - 49) + year + L
// ------------------------------------------------------------------------
function _daysToDate(uint256 _days)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day
)
{
int256 __days = int256(_days);
int256 L = __days + 68569 + OFFSET19700101;
int256 N = (4 * L) / 146097;
L = L - (146097 * N + 3) / 4;
int256 _year = (4000 * (L + 1)) / 1461001;
L = L - (1461 * _year) / 4 + 31;
int256 _month = (80 * L) / 2447;
int256 _day = L - (2447 * _month) / 80;
L = _month / 11;
_month = _month + 2 - 12 * L;
_year = 100 * (N - 49) + _year + L;
year = uint256(_year);
month = uint256(_month);
day = uint256(_day);
}
function timestampFromDate(
uint256 year,
uint256 month,
uint256 day
) internal pure returns (uint256 timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
}
function timestampFromDateTime(
uint256 year,
uint256 month,
uint256 day,
uint256 hour,
uint256 minute,
uint256 second
) internal pure returns (uint256 timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;
}
function timestampToDate(uint256 timestamp)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day
)
{
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function timestampToDateTime(uint256 timestamp)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day,
uint256 hour,
uint256 minute,
uint256 second
)
{
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint256 secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
secs = secs % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
second = secs % SECONDS_PER_MINUTE;
}
function isValidDate(
uint256 year,
uint256 month,
uint256 day
) internal pure returns (bool valid) {
if (year >= 1970 && month > 0 && month <= 12) {
uint256 daysInMonth = _getDaysInMonth(year, month);
if (day > 0 && day <= daysInMonth) {
valid = true;
}
}
}
function isValidDateTime(
uint256 year,
uint256 month,
uint256 day,
uint256 hour,
uint256 minute,
uint256 second
) internal pure returns (bool valid) {
if (isValidDate(year, month, day)) {
if (hour < 24 && minute < 60 && second < 60) {
valid = true;
}
}
}
function isLeapYear(uint256 timestamp) internal pure returns (bool leapYear) {
(uint256 year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
leapYear = _isLeapYear(year);
}
function _isLeapYear(uint256 year) internal pure returns (bool leapYear) {
leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) {
weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
}
function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) {
weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
}
function getDaysInMonth(uint256 timestamp) internal pure returns (uint256 daysInMonth) {
(uint256 year, uint256 month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);
daysInMonth = _getDaysInMonth(year, month);
}
function _getDaysInMonth(uint256 year, uint256 month) internal pure returns (uint256 daysInMonth) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
daysInMonth = 31;
} else if (month != 2) {
daysInMonth = 30;
} else {
daysInMonth = _isLeapYear(year) ? 29 : 28;
}
}
// 1 = Monday, 7 = Sunday
function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) {
uint256 _days = timestamp / SECONDS_PER_DAY;
dayOfWeek = ((_days + 3) % 7) + 1;
}
function getYear(uint256 timestamp) internal pure returns (uint256 year) {
(year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getMonth(uint256 timestamp) internal pure returns (uint256 month) {
(, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getDay(uint256 timestamp) internal pure returns (uint256 day) {
(, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getHour(uint256 timestamp) internal pure returns (uint256 hour) {
uint256 secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
}
function getMinute(uint256 timestamp) internal pure returns (uint256 minute) {
uint256 secs = timestamp % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
}
function getSecond(uint256 timestamp) internal pure returns (uint256 second) {
second = timestamp % SECONDS_PER_MINUTE;
}
function addYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year += _years;
uint256 daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
require(newTimestamp >= timestamp);
}
function addMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
month += _months;
year += (month - 1) / 12;
month = ((month - 1) % 12) + 1;
uint256 daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
require(newTimestamp >= timestamp);
}
function addDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp + _days * SECONDS_PER_DAY;
require(newTimestamp >= timestamp);
}
function addHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
require(newTimestamp >= timestamp);
}
function addMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
require(newTimestamp >= timestamp);
}
function addSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp + _seconds;
require(newTimestamp >= timestamp);
}
function subYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year -= _years;
uint256 daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
require(newTimestamp <= timestamp);
}
function subMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint256 yearMonth = year * 12 + (month - 1) - _months;
year = yearMonth / 12;
month = (yearMonth % 12) + 1;
uint256 daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
require(newTimestamp <= timestamp);
}
function subDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp - _days * SECONDS_PER_DAY;
require(newTimestamp <= timestamp);
}
function subHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
require(newTimestamp <= timestamp);
}
function subMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
require(newTimestamp <= timestamp);
}
function subSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {
newTimestamp = timestamp - _seconds;
require(newTimestamp <= timestamp);
}
function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _years) {
require(fromTimestamp <= toTimestamp);
(uint256 fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
(uint256 toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_years = toYear - fromYear;
}
function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _months) {
require(fromTimestamp <= toTimestamp);
(uint256 fromYear, uint256 fromMonth, ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
(uint256 toYear, uint256 toMonth, ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
}
function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _days) {
require(fromTimestamp <= toTimestamp);
_days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
}
function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _hours) {
require(fromTimestamp <= toTimestamp);
_hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
}
function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _minutes) {
require(fromTimestamp <= toTimestamp);
_minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
}
function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _seconds) {
require(fromTimestamp <= toTimestamp);
_seconds = toTimestamp - fromTimestamp;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IStore.sol";
import "../interfaces/ILendingStrategy.sol";
import "./PriceLibV1.sol";
import "./RegistryLibV1.sol";
library StrategyLibV1 {
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
using RegistryLibV1 for IStore;
uint256 public constant DEFAULT_LENDING_PERIOD = 180 days;
uint256 public constant DEFAULT_WITHDRAWAL_WINDOW = 7 days;
event StrategyAdded(address indexed strategy);
event RiskPoolingPeriodSet(bytes32 indexed key, uint256 lendingPeriod, uint256 withdrawalWindow);
event MaxLendingRatioSet(uint256 ratio);
/**
* @dev Hash key of the "active strategy flag".
*
* Warning: this function does not validate the input arguments.
*
* @param strategyAddress Enter a strategy address
*
*/
function _getIsActiveStrategyKey(address strategyAddress) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE, strategyAddress));
}
/**
* @dev Hash key of the "disabled strategy flag".
*
* Warning: this function does not validate the input arguments.
*
* @param strategyAddress Enter a strategy address
*
*/
function _getIsDisabledStrategyKey(address strategyAddress) private pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED, strategyAddress));
}
/**
* @dev Disables a strategy
*
* @custom:suppress-address-trust-issue The address `toFind` can be trusted since we are not treating it like a contract.
*
*/
function disableStrategyInternal(IStore s, address toFind) external {
_disableStrategy(s, toFind);
s.setAddressArrayByKey(ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED, toFind);
}
/**
* @dev Deletes a strategy
*
* @custom:suppress-address-trust-issue The address `toFind` can be trusted since we are not treating it like a contract.
*
*/
function deleteStrategyInternal(IStore s, address toFind) external {
_deleteStrategy(s, toFind);
}
function addStrategiesInternal(IStore s, address[] calldata strategies) external {
for (uint256 i = 0; i < strategies.length; i++) {
address strategy = strategies[i];
_addStrategy(s, strategy);
}
}
function getRiskPoolingPeriodsInternal(IStore s, bytes32 coverKey) external view returns (uint256 lendingPeriod, uint256 withdrawalWindow) {
lendingPeriod = s.getUintByKey(getLendingPeriodKeyInternal(coverKey));
withdrawalWindow = s.getUintByKey(getWithdrawalWindowKeyInternal(coverKey));
if (lendingPeriod == 0) {
lendingPeriod = s.getUintByKey(getLendingPeriodKeyInternal(0));
withdrawalWindow = s.getUintByKey(getWithdrawalWindowKeyInternal(0));
}
lendingPeriod = lendingPeriod == 0 ? DEFAULT_LENDING_PERIOD : lendingPeriod;
withdrawalWindow = withdrawalWindow == 0 ? DEFAULT_WITHDRAWAL_WINDOW : withdrawalWindow;
}
function setRiskPoolingPeriodsInternal(
IStore s,
bytes32 coverKey,
uint256 lendingPeriod,
uint256 withdrawalWindow
) external {
s.setUintByKey(getLendingPeriodKeyInternal(coverKey), lendingPeriod);
s.setUintByKey(getWithdrawalWindowKeyInternal(coverKey), withdrawalWindow);
emit RiskPoolingPeriodSet(coverKey, lendingPeriod, withdrawalWindow);
}
/**
* @dev Hash key of the "lending period" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getLendingPeriodKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
if (coverKey > 0) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_LENDING_PERIOD, coverKey));
}
return ProtoUtilV1.NS_COVER_LIQUIDITY_LENDING_PERIOD;
}
function getMaxLendingRatioInternal(IStore s) external view returns (uint256) {
return s.getUintByKey(getMaxLendingRatioKeyInternal());
}
function setMaxLendingRatioInternal(IStore s, uint256 ratio) external {
s.setUintByKey(getMaxLendingRatioKeyInternal(), ratio);
emit MaxLendingRatioSet(ratio);
}
/**
* @dev Hash key of the "maximum lending ratio" for the given cover.
*/
function getMaxLendingRatioKeyInternal() public pure returns (bytes32) {
return ProtoUtilV1.NS_COVER_LIQUIDITY_MAX_LENDING_RATIO;
}
/**
* @dev Hash key of the "withdrawal window duration" for the given cover.
*
* Warning: this function does not validate the cover key supplied.
*
* @param coverKey Enter cover key
*
*/
function getWithdrawalWindowKeyInternal(bytes32 coverKey) public pure returns (bytes32) {
if (coverKey > 0) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_WITHDRAWAL_WINDOW, coverKey));
}
return ProtoUtilV1.NS_COVER_LIQUIDITY_WITHDRAWAL_WINDOW;
}
function _addStrategy(IStore s, address deployedOn) private {
ILendingStrategy strategy = ILendingStrategy(deployedOn);
require(strategy.getWeight() <= ProtoUtilV1.MULTIPLIER, "Weight too much");
s.setBoolByKey(_getIsActiveStrategyKey(deployedOn), true);
s.setAddressArrayByKey(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE, deployedOn);
emit StrategyAdded(deployedOn);
}
function _disableStrategy(IStore s, address toFind) private {
bytes32 key = ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE;
uint256 pos = s.getAddressArrayItemPosition(key, toFind);
require(pos > 0, "Invalid strategy");
s.deleteAddressArrayItem(key, toFind);
s.setBoolByKey(_getIsActiveStrategyKey(toFind), false);
s.setBoolByKey(_getIsDisabledStrategyKey(toFind), true);
}
function _deleteStrategy(IStore s, address toFind) private {
bytes32 key = ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED;
uint256 pos = s.getAddressArrayItemPosition(key, toFind);
require(pos > 0, "Invalid strategy");
s.deleteAddressArrayItem(key, toFind);
s.setBoolByKey(_getIsDisabledStrategyKey(toFind), false);
}
function getDisabledStrategiesInternal(IStore s) external view returns (address[] memory strategies) {
return s.getAddressArrayByKey(ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED);
}
function getActiveStrategiesInternal(IStore s) external view returns (address[] memory strategies) {
return s.getAddressArrayByKey(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE);
}
/**
* @dev Hash key of the "strategy outs" for the given cover and token.
*
* Warning: this function does not validate the cover key and token supplied.
*
* @param coverKey Enter cover key
* @param token Enter the token address
*
*/
function getStrategyOutKeyInternal(bytes32 coverKey, address token) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_STRATEGY_OUT, coverKey, token));
}
/**
* @dev Hash key of the "outs" to a specific strategy for the given cover and token.
*
* Warning: this function does not validate the cover key and token supplied.
*
* @param coverKey Enter cover key
* @param token Enter the token address
*
*/
function getSpecificStrategyOutKeyInternal(
bytes32 coverKey,
bytes32 strategyName,
address token
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_STRATEGY_OUT, coverKey, strategyName, token));
}
function getAmountInStrategiesInternal(
IStore s,
bytes32 coverKey,
address token
) public view returns (uint256) {
bytes32 k = getStrategyOutKeyInternal(coverKey, token);
return s.getUintByKey(k);
}
function getAmountInStrategyInternal(
IStore s,
bytes32 coverKey,
bytes32 strategyName,
address token
) public view returns (uint256) {
bytes32 k = getSpecificStrategyOutKeyInternal(coverKey, strategyName, token);
return s.getUintByKey(k);
}
function preTransferToStrategyInternal(
IStore s,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 amount
) external {
if (s.getStablecoinAddressInternal() != address(token)) {
return;
}
_addToStrategyOut(s, coverKey, address(token), amount);
_addToSpecificStrategyOut(s, coverKey, strategyName, address(token), amount);
}
function postReceiveFromStrategyInternal(
IStore s,
IERC20 token,
bytes32 coverKey,
bytes32 strategyName,
uint256 received
) external returns (uint256 income, uint256 loss) {
if (s.getStablecoinAddressInternal() != address(token)) {
return (income, loss);
}
uint256 amountInThisStrategy = getAmountInStrategyInternal(s, coverKey, strategyName, address(token));
income = received > amountInThisStrategy ? received - amountInThisStrategy : 0;
loss = received < amountInThisStrategy ? amountInThisStrategy - received : 0;
_reduceStrategyOut(s, coverKey, address(token), amountInThisStrategy);
_clearSpecificStrategyOut(s, coverKey, strategyName, address(token));
_logIncomes(s, coverKey, strategyName, income, loss);
}
function _addToStrategyOut(
IStore s,
bytes32 coverKey,
address token,
uint256 amountToAdd
) private {
bytes32 k = getStrategyOutKeyInternal(coverKey, token);
s.addUintByKey(k, amountToAdd);
}
function _reduceStrategyOut(
IStore s,
bytes32 coverKey,
address token,
uint256 amount
) private {
bytes32 k = getStrategyOutKeyInternal(coverKey, token);
s.subtractUintByKey(k, amount);
}
function _addToSpecificStrategyOut(
IStore s,
bytes32 coverKey,
bytes32 strategyName,
address token,
uint256 amountToAdd
) private {
bytes32 k = getSpecificStrategyOutKeyInternal(coverKey, strategyName, token);
s.addUintByKey(k, amountToAdd);
}
function _clearSpecificStrategyOut(
IStore s,
bytes32 coverKey,
bytes32 strategyName,
address token
) private {
bytes32 k = getSpecificStrategyOutKeyInternal(coverKey, strategyName, token);
s.deleteUintByKey(k);
}
function _logIncomes(
IStore s,
bytes32 coverKey,
bytes32 strategyName,
uint256 income,
uint256 loss
) private {
// Overall Income
s.addUintByKey(ProtoUtilV1.NS_VAULT_LENDING_INCOMES, income);
// By Cover
s.addUintByKey(keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_LENDING_INCOMES, coverKey)), income);
// By Cover on This Strategy
s.addUintByKey(keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_LENDING_INCOMES, coverKey, strategyName)), income);
// Overall Loss
s.addUintByKey(ProtoUtilV1.NS_VAULT_LENDING_LOSSES, loss);
// By Cover
s.addUintByKey(keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_LENDING_LOSSES, coverKey)), loss);
// By Cover on This Strategy
s.addUintByKey(keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_LENDING_LOSSES, coverKey, strategyName)), loss);
}
function getStablecoinOwnedByVaultInternal(IStore s, bytes32 coverKey) external view returns (uint256) {
address stablecoin = s.getStablecoinAddressInternal();
uint256 balance = IERC20(stablecoin).balanceOf(s.getVaultAddress(coverKey));
uint256 inStrategies = getAmountInStrategiesInternal(s, coverKey, stablecoin);
return balance + inStrategies;
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./ProtoUtilV1.sol";
import "./StoreKeyUtil.sol";
import "../interfaces/ICover.sol";
import "../interfaces/IPolicy.sol";
import "../interfaces/IBondPool.sol";
import "../interfaces/ICoverStake.sol";
import "../interfaces/ICxTokenFactory.sol";
import "../interfaces/ICoverReassurance.sol";
import "../interfaces/IGovernance.sol";
import "../interfaces/IVault.sol";
import "../interfaces/IVaultFactory.sol";
library RegistryLibV1 {
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
function getGovernanceContract(IStore s) external view returns (IGovernance) {
return IGovernance(s.getContractInternal(ProtoUtilV1.CNS_GOVERNANCE, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getResolutionContract(IStore s) external view returns (IGovernance) {
return IGovernance(s.getContractInternal(ProtoUtilV1.CNS_GOVERNANCE_RESOLUTION, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getStakingContract(IStore s) external view returns (ICoverStake) {
return ICoverStake(s.getContractInternal(ProtoUtilV1.CNS_COVER_STAKE, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getCxTokenFactory(IStore s) external view returns (ICxTokenFactory) {
return ICxTokenFactory(s.getContractInternal(ProtoUtilV1.CNS_COVER_CXTOKEN_FACTORY, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getPolicyContract(IStore s) external view returns (IPolicy) {
return IPolicy(s.getContractInternal(ProtoUtilV1.CNS_COVER_POLICY, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getReassuranceContract(IStore s) external view returns (ICoverReassurance) {
return ICoverReassurance(s.getContractInternal(ProtoUtilV1.CNS_COVER_REASSURANCE, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY));
}
function getBondPoolContract(IStore s) external view returns (IBondPool) {
return IBondPool(getBondPoolAddress(s));
}
function getProtocolContract(IStore s, bytes32 cns) public view returns (address) {
return s.getAddressByKeys(ProtoUtilV1.NS_CONTRACTS, cns);
}
function getProtocolContract(
IStore s,
bytes32 cns,
bytes32 key
) public view returns (address) {
return s.getAddressByKeys(ProtoUtilV1.NS_CONTRACTS, cns, key);
}
function getCoverContract(IStore s) external view returns (ICover) {
address vault = getProtocolContract(s, ProtoUtilV1.CNS_COVER);
return ICover(vault);
}
function getVault(IStore s, bytes32 coverKey) external view returns (IVault) {
return IVault(getVaultAddress(s, coverKey));
}
function getVaultAddress(IStore s, bytes32 coverKey) public view returns (address) {
address vault = getProtocolContract(s, ProtoUtilV1.CNS_COVER_VAULT, coverKey);
return vault;
}
function getVaultDelegate(IStore s) external view returns (address) {
address vaultImplementation = getProtocolContract(s, ProtoUtilV1.CNS_COVER_VAULT_DELEGATE);
return vaultImplementation;
}
function getStakingPoolAddress(IStore s) external view returns (address) {
address pool = getProtocolContract(s, ProtoUtilV1.CNS_STAKING_POOL);
return pool;
}
function getBondPoolAddress(IStore s) public view returns (address) {
address pool = getProtocolContract(s, ProtoUtilV1.CNS_BOND_POOL);
return pool;
}
function getVaultFactoryContract(IStore s) external view returns (IVaultFactory) {
address factory = s.getContractInternal(ProtoUtilV1.CNS_COVER_VAULT_FACTORY, ProtoUtilV1.KEY_INTENTIONALLY_EMPTY);
return IVaultFactory(factory);
}
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
interface ICover is IMember {
struct AddCoverArgs {
bytes32 coverKey;
string info;
string tokenName;
string tokenSymbol;
bool supportsProducts;
bool requiresWhitelist;
uint256 stakeWithFee;
uint256 initialReassuranceAmount;
uint256 minStakeToReport;
uint256 reportingPeriod;
uint256 cooldownPeriod;
uint256 claimPeriod;
uint256 floor;
uint256 ceiling;
uint256 reassuranceRate;
uint256 leverageFactor;
}
struct AddProductArgs {
bytes32 coverKey;
bytes32 productKey;
string info;
bool requiresWhitelist;
uint256 productStatus;
uint256 efficiency;
}
struct UpdateProductArgs {
bytes32 coverKey;
bytes32 productKey;
string info;
uint256 productStatus;
uint256 efficiency;
}
event CoverCreated(bytes32 indexed coverKey, string info, string tokenName, string tokenSymbol, bool indexed supportsProducts, bool indexed requiresWhitelist);
event ProductCreated(bytes32 indexed coverKey, bytes32 productKey, string info);
event CoverUpdated(bytes32 indexed coverKey, string info);
event ProductUpdated(bytes32 indexed coverKey, bytes32 productKey, string info);
event ProductStateUpdated(bytes32 indexed coverKey, bytes32 indexed productKey, address indexed updatedBy, bool status, string reason);
event CoverCreatorWhitelistUpdated(address account, bool status);
event CoverUserWhitelistUpdated(bytes32 indexed coverKey, bytes32 indexed productKey, address indexed account, bool status);
event CoverCreationFeeSet(uint256 previous, uint256 current);
event MinCoverCreationStakeSet(uint256 previous, uint256 current);
event MinStakeToAddLiquiditySet(uint256 previous, uint256 current);
event CoverInitialized(address indexed stablecoin, bytes32 withName);
/**
* @dev Initializes this contract
* @param stablecoin Provide the address of the token this cover will be quoted against.
* @param friendlyName Enter a description or ENS name of your liquidity token.
*
*/
function initialize(address stablecoin, bytes32 friendlyName) external;
/**
* @dev 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. <br /> <br />
*
* Through the governance portal, projects will be able redeem
* the full cover fee at a later date. <br /> <br />
*
* **Apply for Fee Redemption** <br />
* https://docs.neptunemutual.com/covers/cover-fee-redemption <br /><br />
*
* As the cover creator, you will earn a portion of all cover fees
* generated in this pool. <br /> <br />
*
* Read the documentation to learn more about the fees: <br />
* https://docs.neptunemutual.com/covers/contract-creators
*
*/
function addCover(AddCoverArgs calldata args) external returns (address);
function addCovers(AddCoverArgs[] calldata args) external returns (address[] memory vaults);
function addProduct(AddProductArgs calldata args) external;
function addProducts(AddProductArgs[] calldata args) external;
function updateProduct(UpdateProductArgs calldata args) external;
/**
* @dev Updates the cover contract.
* This feature is accessible only to the cover owner or protocol owner (governance).
*
* @param coverKey Enter the cover key
* @param info Enter a new IPFS hash to update
*/
function updateCover(bytes32 coverKey, string calldata info) external;
function updateCoverCreatorWhitelist(address[] calldata account, bool[] calldata whitelisted) external;
function updateCoverUsersWhitelist(
bytes32 coverKey,
bytes32 productKey,
address[] calldata accounts,
bool[] calldata statuses
) external;
function disablePolicy(
bytes32 coverKey,
bytes32 productKey,
bool status,
string calldata reason
) external;
function checkIfWhitelistedCoverCreator(address account) external view returns (bool);
function checkIfWhitelistedUser(
bytes32 coverKey,
bytes32 productKey,
address account
) external view returns (bool);
function setCoverCreationFee(uint256 value) external;
function setMinCoverCreationStake(uint256 value) external;
function setMinStakeToAddLiquidity(uint256 value) external;
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IMember.sol";
interface IBondPool is IMember {
struct BondPoolInfoType {
address lpToken;
uint256 marketPrice;
uint256 discountRate;
uint256 vestingTerm;
uint256 maxBond;
uint256 totalNpmAllocated;
uint256 totalNpmDistributed;
uint256 npmAvailable;
uint256 bondContribution;
uint256 claimable;
uint256 unlockDate;
}
struct SetupBondPoolArgs {
address lpToken;
address treasury;
uint256 bondDiscountRate;
uint256 maxBondAmount;
uint256 vestingTerm;
uint256 npmToTopUpNow;
}
event BondPoolSetup(SetupBondPoolArgs args);
event BondCreated(address indexed account, uint256 lpTokens, uint256 npmToVest, uint256 unlockDate);
event BondClaimed(address indexed account, uint256 amount);
function setup(SetupBondPoolArgs calldata args) external;
function createBond(uint256 lpTokens, uint256 minNpmDesired) external;
function claimBond() external;
function getNpmMarketPrice() external view returns (uint256);
function calculateTokensForLp(uint256 lpTokens) external view returns (uint256);
function getInfo(address forAccount) external view returns (BondPoolInfoType memory info);
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IStore.sol";
import "./IMember.sol";
interface ICxTokenFactory is IMember {
event CxTokenDeployed(address cxToken, IStore store, bytes32 indexed coverKey, bytes32 indexed productKey, string tokenName, uint256 indexed expiryDate);
function deploy(
bytes32 coverKey,
bytes32 productKey,
string calldata tokenName,
uint256 expiryDate
) external returns (address);
}/* solhint-disable function-max-lines */
// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IReporter.sol";
import "./IWitness.sol";
import "./IMember.sol";
// solhint-disable-next-line
interface IGovernance is IMember, IReporter, IWitness {
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IReporter {
event Reported(bytes32 indexed coverKey, bytes32 indexed productKey, address reporter, uint256 indexed incidentDate, string info, uint256 initialStake, uint256 resolutionTimestamp);
event Disputed(bytes32 indexed coverKey, bytes32 indexed productKey, address reporter, uint256 indexed incidentDate, string info, uint256 initialStake);
event ReportingBurnRateSet(uint256 previous, uint256 current);
event FirstReportingStakeSet(bytes32 coverKey, uint256 previous, uint256 current);
event ReporterCommissionSet(uint256 previous, uint256 current);
function report(
bytes32 coverKey,
bytes32 productKey,
string calldata info,
uint256 stake
) external;
function dispute(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
string calldata info,
uint256 stake
) external;
function getActiveIncidentDate(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
function getAttestation(
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate
) external view returns (uint256 myStake, uint256 totalStake);
function getRefutation(
bytes32 coverKey,
bytes32 productKey,
address who,
uint256 incidentDate
) external view returns (uint256 myStake, uint256 totalStake);
function getReporter(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (address);
function getResolutionTimestamp(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
function setFirstReportingStake(bytes32 coverKey, uint256 value) external;
function getFirstReportingStake(bytes32 coverKey) external view returns (uint256);
function setReportingBurnRate(uint256 value) external;
function setReporterCommission(uint256 value) external;
}// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IWitness {
event Attested(bytes32 indexed coverKey, bytes32 indexed productKey, address witness, uint256 indexed incidentDate, uint256 stake);
event Refuted(bytes32 indexed coverKey, bytes32 indexed productKey, address witness, uint256 indexed incidentDate, uint256 stake);
function attest(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
uint256 stake
) external;
function refute(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
uint256 stake
) external;
function getStatus(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
function isCoverNormal(bytes32 coverKey) external view returns (bool);
function getStakes(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate
) external view returns (uint256, uint256);
function getStakesOf(
bytes32 coverKey,
bytes32 productKey,
uint256 incidentDate,
address account
) external view returns (uint256, uint256);
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {
"contracts/libraries/AccessControlLibV1.sol": {
"AccessControlLibV1": "0x405848de6da43460c73341bc27b1aee3abf428ee"
},
"contracts/libraries/BaseLibV1.sol": {
"BaseLibV1": "0x3def8f7843d024e9ef03d9db81626393d04f1c38"
},
"contracts/libraries/ProtoUtilV1.sol": {
"ProtoUtilV1": "0x1693cc00b92a8be4d2cfb8c87f5a134cd71c9de3"
},
"contracts/libraries/ValidationLibV1.sol": {
"ValidationLibV1": "0x2736f310069457abcb6f4173fc2eb48c4679caf0"
},
"contracts/libraries/VaultFactoryLibV1.sol": {
"VaultFactoryLibV1": "0x6af1f22fb8e0316eeaad37e6b408638bffd9c2e3"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IStore","name":"store","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"bytes32","name":"coverKey","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"}],"name":"VaultDeployed","type":"event"},{"inputs":[{"internalType":"bytes32","name":"coverKey","type":"bytes32"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"name":"deploy","outputs":[{"internalType":"address","name":"addr","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getName","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"sendTo","type":"address"}],"name":"recoverEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"sendTo","type":"address"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"s","outputs":[{"internalType":"contract IStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50604051610dbb380380610dbb83398101604081905261002f916100a5565b6001600055806001600160a01b03811661007f5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642053746f726560981b604482015260640160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055506100d5565b6000602082840312156100b757600080fd5b81516001600160a01b03811681146100ce57600080fd5b9392505050565b610cd7806100e46000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806386b714e21161005057806386b714e2146100e7578063b2670cc51461012c578063feaea5861461013f57600080fd5b806317d7de7c1461007757806352d5999f146100ac57806354fd4d50146100c1575b600080fd5b7f5661756c7420466163746f7279000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b6100bf6100ba36600461094d565b610152565b005b7f76302e3100000000000000000000000000000000000000000000000000000000610099565b6001546101079073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a3565b61010761013a3660046109ba565b61038b565b6100bf61014d366004610a34565b6106eb565b6002600054036101c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b15801561024557600080fd5b505af4158015610259573d6000803e3d6000fd5b50506001546040517ff268c9e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015273405848de6da43460c73341bc27b1aee3abf428ee925063f268c9e0915060240160006040518083038186803b1580156102da57600080fd5b505af41580156102ee573d6000803e3d6000fd5b50506040517f9075c92200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152733def8f7843d024e9ef03d9db81626393d04f1c389250639075c922915060240160006040518083038186803b15801561036b57600080fd5b505af415801561037f573d6000803e3d6000fd5b50506001600055505050565b60006002600054036103f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101ba565b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b15801561047b57600080fd5b505af415801561048f573d6000803e3d6000fd5b50506001546040517f2ee83ef900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09250632ee83ef9915060240160006040518083038186803b15801561051057600080fd5b505af4158015610524573d6000803e3d6000fd5b50506001546040517fc894f4bf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820181905260009350839250736af1f22fb8e0316eeaad37e6b408638bffd9c2e391634453366891908b908b908b908b908b90731693cc00b92a8be4d2cfb8c87f5a134cd71c9de39063c894f4bf90602401602060405180830381865af41580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190610a6d565b6040518863ffffffff1660e01b815260040161061e9796959493929190610ad3565b600060405180830381865af415801561063b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106819190810190610b64565b915091508082516020840134f59250823b61069b57600080fd5b877fa400bcd04d15f0c3e86c45e1a608862b25e8a4b0f00ef449c0d60cba0063448384898989896040516106d3959493929190610c52565b60405180910390a25050600160005595945050505050565b600260005403610757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101ba565b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b1580156107d957600080fd5b505af41580156107ed573d6000803e3d6000fd5b50506001546040517ff268c9e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015273405848de6da43460c73341bc27b1aee3abf428ee925063f268c9e0915060240160006040518083038186803b15801561086e57600080fd5b505af4158015610882573d6000803e3d6000fd5b50506040517f707bf3d400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808616600483015284166024820152733def8f7843d024e9ef03d9db81626393d04f1c38925063707bf3d4915060440160006040518083038186803b15801561090757600080fd5b505af415801561091b573d6000803e3d6000fd5b5050600160005550505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610928565b9392505050565b60008083601f84011261098357600080fd5b50813567ffffffffffffffff81111561099b57600080fd5b6020830191508360208285010111156109b357600080fd5b9250929050565b6000806000806000606086880312156109d257600080fd5b85359450602086013567ffffffffffffffff808211156109f157600080fd5b6109fd89838a01610971565b90965094506040880135915080821115610a1657600080fd5b50610a2388828901610971565b969995985093965092949392505050565b60008060408385031215610a4757600080fd5b8235610a5281610928565b91506020830135610a6281610928565b809150509250929050565b600060208284031215610a7f57600080fd5b815161096a81610928565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600073ffffffffffffffffffffffffffffffffffffffff808a16835288602084015260a06040840152610b0a60a08401888a610a8a565b8381036060850152610b1d818789610a8a565b92505080841660808401525098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060408385031215610b7757600080fd5b825167ffffffffffffffff80821115610b8f57600080fd5b818501915085601f830112610ba357600080fd5b815181811115610bb557610bb5610b35565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610bfb57610bfb610b35565b81604052828152602093508884848701011115610c1757600080fd5b600091505b82821015610c395784820184015181830185015290830190610c1c565b6000928101840192909252509401519395939450505050565b73ffffffffffffffffffffffffffffffffffffffff86168152606060208201526000610c82606083018688610a8a565b8281036040840152610c95818587610a8a565b9897505050505050505056fea26469706673582212207392d38ccb1c0c74a2c41295f5b50098fc724b94f2a0554057a37c8baec620f064736f6c634300081100330000000000000000000000006579df8f986e4a982f200dafa0c1b955a438f620
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100725760003560e01c806386b714e21161005057806386b714e2146100e7578063b2670cc51461012c578063feaea5861461013f57600080fd5b806317d7de7c1461007757806352d5999f146100ac57806354fd4d50146100c1575b600080fd5b7f5661756c7420466163746f7279000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b6100bf6100ba36600461094d565b610152565b005b7f76302e3100000000000000000000000000000000000000000000000000000000610099565b6001546101079073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a3565b61010761013a3660046109ba565b61038b565b6100bf61014d366004610a34565b6106eb565b6002600054036101c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b15801561024557600080fd5b505af4158015610259573d6000803e3d6000fd5b50506001546040517ff268c9e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015273405848de6da43460c73341bc27b1aee3abf428ee925063f268c9e0915060240160006040518083038186803b1580156102da57600080fd5b505af41580156102ee573d6000803e3d6000fd5b50506040517f9075c92200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152733def8f7843d024e9ef03d9db81626393d04f1c389250639075c922915060240160006040518083038186803b15801561036b57600080fd5b505af415801561037f573d6000803e3d6000fd5b50506001600055505050565b60006002600054036103f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101ba565b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b15801561047b57600080fd5b505af415801561048f573d6000803e3d6000fd5b50506001546040517f2ee83ef900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09250632ee83ef9915060240160006040518083038186803b15801561051057600080fd5b505af4158015610524573d6000803e3d6000fd5b50506001546040517fc894f4bf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820181905260009350839250736af1f22fb8e0316eeaad37e6b408638bffd9c2e391634453366891908b908b908b908b908b90731693cc00b92a8be4d2cfb8c87f5a134cd71c9de39063c894f4bf90602401602060405180830381865af41580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190610a6d565b6040518863ffffffff1660e01b815260040161061e9796959493929190610ad3565b600060405180830381865af415801561063b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106819190810190610b64565b915091508082516020840134f59250823b61069b57600080fd5b877fa400bcd04d15f0c3e86c45e1a608862b25e8a4b0f00ef449c0d60cba0063448384898989896040516106d3959493929190610c52565b60405180910390a25050600160005595945050505050565b600260005403610757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101ba565b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152732736f310069457abcb6f4173fc2eb48c4679caf09063f5bd1af29060240160006040518083038186803b1580156107d957600080fd5b505af41580156107ed573d6000803e3d6000fd5b50506001546040517ff268c9e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015273405848de6da43460c73341bc27b1aee3abf428ee925063f268c9e0915060240160006040518083038186803b15801561086e57600080fd5b505af4158015610882573d6000803e3d6000fd5b50506040517f707bf3d400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808616600483015284166024820152733def8f7843d024e9ef03d9db81626393d04f1c38925063707bf3d4915060440160006040518083038186803b15801561090757600080fd5b505af415801561091b573d6000803e3d6000fd5b5050600160005550505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610928565b9392505050565b60008083601f84011261098357600080fd5b50813567ffffffffffffffff81111561099b57600080fd5b6020830191508360208285010111156109b357600080fd5b9250929050565b6000806000806000606086880312156109d257600080fd5b85359450602086013567ffffffffffffffff808211156109f157600080fd5b6109fd89838a01610971565b90965094506040880135915080821115610a1657600080fd5b50610a2388828901610971565b969995985093965092949392505050565b60008060408385031215610a4757600080fd5b8235610a5281610928565b91506020830135610a6281610928565b809150509250929050565b600060208284031215610a7f57600080fd5b815161096a81610928565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600073ffffffffffffffffffffffffffffffffffffffff808a16835288602084015260a06040840152610b0a60a08401888a610a8a565b8381036060850152610b1d818789610a8a565b92505080841660808401525098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060408385031215610b7757600080fd5b825167ffffffffffffffff80821115610b8f57600080fd5b818501915085601f830112610ba357600080fd5b815181811115610bb557610bb5610b35565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610bfb57610bfb610b35565b81604052828152602093508884848701011115610c1757600080fd5b600091505b82821015610c395784820184015181830185015290830190610c1c565b6000928101840192909252509401519395939450505050565b73ffffffffffffffffffffffffffffffffffffffff86168152606060208201526000610c82606083018688610a8a565b8281036040840152610c95818587610a8a565b9897505050505050505056fea26469706673582212207392d38ccb1c0c74a2c41295f5b50098fc724b94f2a0554057a37c8baec620f064736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006579df8f986e4a982f200dafa0c1b955a438f620
-----Decoded View---------------
Arg [0] : store (address): 0x6579dF8f986e4A982F200DAfa0c1b955A438f620
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000006579df8f986e4a982f200dafa0c1b955a438f620
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.