Contract Overview
Balance:
0 MATIC
My Name Tag:
Not Available
Txn Hash |
Method
|
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xbf4f953383fe2529d633e1d0750fb09701eec76b75781cd869fafc2a4517215d | 0x60806040 | 25704660 | 438 days 4 hrs ago | 0x78ce422bdf870c6f8b32ecb322a54e8fa7b1bd12 | IN | Create: cxTokenFactory | 0 MATIC | 0.0190874 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
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:
cxTokenFactory
Compiler Version
v0.8.0+commit.c7dfd78e
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/ICxTokenFactory.sol"; import "../../libraries/cxTokenFactoryLibV1.sol"; import "../../libraries/ValidationLibV1.sol"; import "../Recoverable.sol"; /** * @title cxToken Factory Contract * @dev As and when required by the protocol, * the cxTokenFactory contract creates new instances of * cxTokens on demand. */ // slither-disable-next-line naming-convention contract cxTokenFactory is ICxTokenFactory, Recoverable { // solhint-disable-previous-line using ProtoUtilV1 for bytes; using ProtoUtilV1 for IStore; using ValidationLibV1 for IStore; using StoreKeyUtil 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 cxTokens * @param s Provide the store contract instance * @param key Enter the cover key related to this cxToken instance * @param expiryDate Specify the expiry date of this cxToken instance */ function deploy( IStore s, bytes32 key, uint256 expiryDate ) external override nonReentrant returns (address deployed) { // @suppress-acl Can only be called by the latest policy contract s.mustNotBePaused(); s.mustBeValidCoverKey(key); s.senderMustBePolicyContract(); require(expiryDate > 0, "Please specify expiry date"); (bytes memory bytecode, bytes32 salt) = cxTokenFactoryLibV1.getByteCode(s, key, expiryDate); require(s.getAddress(salt) == address(0), "Already deployed"); // solhint-disable-next-line assembly { deployed := 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(deployed)) { // @suppress-revert This is correct usage revert(0, 0) } } s.setAddress(salt, deployed); s.setBoolByKeys(ProtoUtilV1.NS_COVER_CXTOKEN, deployed, true); s.setAddressArrayByKeys(ProtoUtilV1.NS_COVER_CXTOKEN, key, deployed); emit CxTokenDeployed(key, deployed, expiryDate); } /** * @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_CXTOKEN_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 { 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); 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 key); event Entered(bytes32 indexed key, address indexed account); event Exited(bytes32 indexed key, address indexed account); function key() external view returns (bytes32); function sc() external view returns (address); /** * @dev Adds liquidity to the specified cover contract * @param coverKey Enter the cover key * @param amount Enter the amount of liquidity token to supply. * @param npmStake Enter the amount of NPM token to stake. Will be locked for a minimum window of one withdrawal period. */ function addLiquidity( bytes32 coverKey, uint256 amount, uint256 npmStake ) 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 (uint256[] memory result); /** * @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 ICxTokenFactory is IMember { event CxTokenDeployed(bytes32 indexed key, address cxToken, uint256 expiryDate); function deploy( IStore s, bytes32 key, uint256 expiryDate ) external returns (address); }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "../core/cxToken/cxToken.sol"; // slither-disable-next-line naming-convention library cxTokenFactoryLibV1 { // solhint-disable-previous-line /** * @dev Gets the bytecode of the `cxToken` contract * @param s Provide the store instance * @param key Provide the cover key * @param expiryDate Specify the expiry date of this cxToken instance */ function getByteCode( IStore s, bytes32 key, uint256 expiryDate ) external pure returns (bytes memory bytecode, bytes32 salt) { salt = keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_CXTOKEN, key, expiryDate)); //slither-disable-next-line too-many-digits bytecode = abi.encodePacked(type(cxToken).creationCode, abi.encode(s, key, expiryDate)); } }
// 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"; import "./StoreKeyUtil.sol"; import "./RegistryLibV1.sol"; import "./CoverUtilV1.sol"; import "./GovernanceUtilV1.sol"; import "./AccessControlLibV1.sol"; import "../interfaces/IStore.sol"; import "../interfaces/IPausable.sol"; import "../interfaces/ICxToken.sol"; library ValidationLibV1 { using ProtoUtilV1 for IStore; using StoreKeyUtil for IStore; using CoverUtilV1 for IStore; using GovernanceUtilV1 for IStore; using RegistryLibV1 for IStore; /********************************************************************************************* _______ ______ ________ ______ | | |\ / |______|_____/ |_____ |_____| \/ |______| \_ *********************************************************************************************/ /** * @dev Reverts if the protocol is paused */ function mustNotBePaused(IStore s) public view { address protocol = s.getProtocolAddress(); require(IPausable(protocol).paused() == false, "Protocol is paused"); } /** * @dev Reverts if the key does not resolve in a valid cover contract * or if the cover is under governance. * @param key Enter the cover key to check */ function mustHaveNormalCoverStatus(IStore s, bytes32 key) external view { require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, key), "Cover does not exist"); require(s.getCoverStatus(key) == CoverUtilV1.CoverStatus.Normal, "Status not normal"); } /** * @dev Reverts if the key does not resolve in a valid cover contract * or if the cover is under governance. * @param key Enter the cover key to check */ function mustHaveStoppedCoverStatus(IStore s, bytes32 key) external view { require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, key), "Cover does not exist"); require(s.getCoverStatus(key) == CoverUtilV1.CoverStatus.Stopped, "Cover isn't stopped"); } /** * @dev Reverts if the key does not resolve in a valid cover contract. * @param key Enter the cover key to check */ function mustBeValidCoverKey(IStore s, bytes32 key) external view { require(s.getBoolByKeys(ProtoUtilV1.NS_COVER, key), "Cover does not exist"); } /** * @dev Reverts if the sender is not the cover owner * @param key Enter the cover key to check * @param sender The `msg.sender` value */ function mustBeCoverOwner( IStore s, bytes32 key, address sender ) public view { bool isCoverOwner = s.getCoverOwner(key) == sender; require(isCoverOwner, "Forbidden"); } /** * @dev Reverts if the sender is not the cover owner or the cover contract * @param key Enter the cover key to check * @param sender The `msg.sender` value */ function mustBeCoverOwnerOrCoverContract( IStore s, bytes32 key, address sender ) external view { bool isCoverOwner = s.getCoverOwner(key) == sender; bool isCoverContract = address(s.getCoverContract()) == sender; require(isCoverOwner || isCoverContract, "Forbidden"); } function senderMustBeCoverOwnerOrAdmin(IStore s, bytes32 key) external view { if (AccessControlLibV1.hasAccess(s, AccessControlLibV1.NS_ROLES_ADMIN, msg.sender) == false) { mustBeCoverOwner(s, key, 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 key) external view { address vault = s.getVaultAddress(key); 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) external view { bool callerIsStrategyContract = s.getBoolByKey(_getIsActiveStrategyKey(caller)); require(callerIsStrategyContract == true, "Not a strategy contract"); } function callerMustBeSpecificStrategyContract( IStore s, address caller, bytes32 /*strategyName*/ ) external view { // @todo bool callerIsStrategyContract = s.getBoolByKey(_getIsActiveStrategyKey(caller)); require(callerIsStrategyContract == true, "Not a strategy contract"); } function _getIsActiveStrategyKey(address strategyAddress) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE, strategyAddress)); } function senderMustBeProtocolMember(IStore s) external view { require(s.isProtocolMember(msg.sender), "Forbidden"); } /********************************************************************************************* ______ _____ _ _ _______ ______ __ _ _______ __ _ _______ _______ | ____ | | \ / |______ |_____/ | \ | |_____| | \ | | |______ |_____| |_____| \/ |______ | \_ | \_| | | | \_| |_____ |______ *********************************************************************************************/ function mustBeReporting(IStore s, bytes32 key) external view { require(s.getCoverStatus(key) == CoverUtilV1.CoverStatus.IncidentHappened, "Not reporting"); } function mustBeDisputed(IStore s, bytes32 key) external view { require(s.getCoverStatus(key) == CoverUtilV1.CoverStatus.FalseReporting, "Not disputed"); } function mustBeClaimable(IStore s, bytes32 key) public view { require(s.getCoverStatus(key) == CoverUtilV1.CoverStatus.Claimable, "Not claimable"); } function mustBeClaimingOrDisputed(IStore s, bytes32 key) external view { CoverUtilV1.CoverStatus status = s.getCoverStatus(key); bool claiming = status == CoverUtilV1.CoverStatus.Claimable; bool falseReporting = status == CoverUtilV1.CoverStatus.FalseReporting; require(claiming || falseReporting, "Not reported nor disputed"); } function mustBeReportingOrDisputed(IStore s, bytes32 key) external view { CoverUtilV1.CoverStatus status = s.getCoverStatus(key); bool incidentHappened = status == CoverUtilV1.CoverStatus.IncidentHappened; bool falseReporting = status == CoverUtilV1.CoverStatus.FalseReporting; require(incidentHappened || falseReporting, "Not reported nor disputed"); } function mustBeBeforeResolutionDeadline(IStore s, bytes32 key) external view { uint256 deadline = s.getResolutionDeadlineInternal(key); if (deadline > 0) { require(block.timestamp < deadline, "Emergency resolution deadline over"); // solhint-disable-line } } function mustNotHaveResolutionDeadline(IStore s, bytes32 key) external view { uint256 deadline = s.getResolutionDeadlineInternal(key); require(deadline == 0, "Resolution already has deadline"); } function mustBeAfterResolutionDeadline(IStore s, bytes32 key) public view { uint256 deadline = s.getResolutionDeadlineInternal(key); require(block.timestamp > deadline, "Still unresolved"); // solhint-disable-line } function mustBeValidIncidentDate( IStore s, bytes32 key, uint256 incidentDate ) public view { require(s.getLatestIncidentDate(key) == incidentDate, "Invalid incident date"); } function mustHaveDispute(IStore s, bytes32 key) external view { bool hasDispute = s.getBoolByKey(GovernanceUtilV1.getHasDisputeKey(key)); require(hasDispute == true, "Not disputed"); } function mustNotHaveDispute(IStore s, bytes32 key) external view { bool hasDispute = s.getBoolByKey(GovernanceUtilV1.getHasDisputeKey(key)); require(hasDispute == false, "Already disputed"); } function mustBeDuringReportingPeriod(IStore s, bytes32 key) external view { require(s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_RESOLUTION_TS, key) >= block.timestamp, "Reporting window closed"); // solhint-disable-line } function mustBeAfterReportingPeriod(IStore s, bytes32 key) public view { require(block.timestamp > s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_RESOLUTION_TS, key), "Reporting still active"); // solhint-disable-line } function mustBeValidCxToken( IStore s, bytes32 key, address cxToken, uint256 incidentDate ) public view { require(s.getBoolByKeys(ProtoUtilV1.NS_COVER_CXTOKEN, cxToken) == true, "Unknown cxToken"); bytes32 coverKey = ICxToken(cxToken).coverKey(); require(coverKey == key, "Invalid cxToken"); uint256 expires = ICxToken(cxToken).expiresOn(); require(expires > incidentDate, "Invalid or expired cxToken"); } function mustBeValidClaim( IStore s, bytes32 key, address cxToken, uint256 incidentDate ) external view { // @note: cxTokens are no longer protocol members // as we will end up with way too many contracts // s.mustBeProtocolMember(cxToken); mustBeValidCxToken(s, key, cxToken, incidentDate); mustBeClaimable(s, key); mustBeValidIncidentDate(s, key, incidentDate); mustBeDuringClaimPeriod(s, key); } function mustNotHaveUnstaken( IStore s, address account, bytes32 key, uint256 incidentDate ) public view { uint256 withdrawal = s.getReportingUnstakenAmount(account, key, incidentDate); require(withdrawal == 0, "Already unstaken"); } function validateUnstakeWithoutClaim( IStore s, bytes32 key, uint256 incidentDate ) external view { mustNotBePaused(s); mustNotHaveUnstaken(s, msg.sender, key, 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, key); // @note: when this reporting gets finalized, the emergency resolution deadline resets to 0 // The above code is not useful after finalization but it helps avoid // people calling unstake before a decision is obtained } function validateUnstakeWithClaim( IStore s, bytes32 key, uint256 incidentDate ) external view { mustNotBePaused(s); mustNotHaveUnstaken(s, msg.sender, key, 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, key, 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, key); bool incidentHappened = s.getCoverStatus(key) == CoverUtilV1.CoverStatus.IncidentHappened; if (incidentHappened) { // Incident occurred. Must unstake with claim during the claim period. mustBeDuringClaimPeriod(s, key); return; } // Incident did not occur. mustBeAfterReportingPeriod(s, key); } function mustBeDuringClaimPeriod(IStore s, bytes32 key) public view { uint256 beginsFrom = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_BEGIN_TS, key); uint256 expiresAt = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_EXPIRY_TS, key); 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 key) external view { require(block.timestamp > s.getUintByKeys(ProtoUtilV1.NS_CLAIM_EXPIRY_TS, key), "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 key) external view { bool required = s.checkIfRequiresWhitelist(key); if (required == false) { return; } require(s.getAddressBooleanByKeys(ProtoUtilV1.NS_COVER_USER_WHITELIST, key, msg.sender), "You are not whitelisted"); } }
// 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"; 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 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. * @param token IERC-20 The address of the token contract */ function recoverToken(address token, address sendTo) external override nonReentrant { // @suppress-address-trust-issue, @suppress-malicious-erc20 Although the token can't be trusted, the recovery agent has to check the token code manually. 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 { 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[] memory 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 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 deleteAddressArrayItemByIndex(bytes32 k, uint256 i) external; function getAddressValues(bytes32[] memory 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[] memory 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 getAddressArray(bytes32 k) external view returns (address[] memory); function getAddressArrayItemPosition(bytes32 k, address toFind) external view returns (uint256); function getAddressArrayItemByIndex(bytes32 k, uint256 i) external view returns (address); }
// 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 "../../interfaces/IStore.sol"; import "../../interfaces/ICxToken.sol"; import "../../libraries/ProtoUtilV1.sol"; import "../../libraries/ValidationLibV1.sol"; import "../../libraries/NTransferUtilV2.sol"; import "../Recoverable.sol"; /** * @title cxToken * @dev cxTokens are minted when someone purchases a cover. <br /> <br /> * * When a cover incident is successfully resolved, each unit of cxTokens can be redeemed at 1:1 ratio * of 1 cxToken = 1 DAI/BUSD/USDC (minus platform fees). * */ // slither-disable-next-line naming-convention contract cxToken is ICxToken, Recoverable, ERC20 { // solhint-disable-previous-line using ProtoUtilV1 for IStore; using ValidationLibV1 for IStore; bytes32 public immutable override coverKey; uint256 public immutable override createdOn = block.timestamp; // solhint-disable-line uint256 public immutable override expiresOn; function _getTokenName(bytes32 key) private pure returns (string memory) { return string(abi.encodePacked(string(abi.encodePacked(key)), "-cxtoken")); } /** * @dev Constructs this contract * @param store Provide the store contract instance * @param key Enter the cover key or cover this cxToken instance points to * @param expiry Provide the cover expiry timestamp of this cxToken instance */ constructor( IStore store, bytes32 key, uint256 expiry ) ERC20(_getTokenName(key), "cxUSD") Recoverable(store) { coverKey = key; expiresOn = expiry; } /** * @dev Mints cxTokens when a policy is purchased. * This feature can only be accessed by the latest policy smart contract. * @param key Enter the cover key for which the cxTokens are being minted * @param to Enter the address where the minted token will be sent * @param amount Specify the amount of cxTokens to mint */ function mint( bytes32 key, address to, uint256 amount ) external override nonReentrant { // @suppress-acl Can only be called by the latest policy contract s.mustNotBePaused(); require(amount > 0, "Please specify amount"); require(key == coverKey, "Invalid cover"); s.senderMustBePolicyContract(); super._mint(to, amount); } /** * @dev Burns the tokens held by the sender * @param amount Specify the amount of tokens to burn */ function burn(uint256 amount) external override nonReentrant { // @suppress-acl Marking this as publicly accessible require(amount > 0, "Please specify amount"); s.mustNotBePaused(); super._burn(msg.sender, amount); } function _beforeTokenTransfer( address, address to, uint256 ) internal view override { // solhint-disable-next-line if (block.timestamp > expiresOn) { require(to == address(0), "Expired cxToken"); } } }
// 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 {} }
// 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 { function mint( bytes32 key, address to, uint256 amount ) external; function burn(uint256 amount) external; function createdOn() external view returns (uint256); function expiresOn() external view returns (uint256); function coverKey() external view returns (bytes32); }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "../interfaces/IStore.sol"; import "../interfaces/IProtocol.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./StoreKeyUtil.sol"; library ProtoUtilV1 { using StoreKeyUtil for IStore; uint256 public constant MULTIPLIER = 10_000; // @todo Configure this magic number. uint256 public constant MAX_LENDING_RATIO = 500; // 5% (divided by 10,000) /// @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_REASSURANCE_VAULT = "cns:core:reassurance:vault"; bytes32 public constant CNS_PRICE_DISCOVERY = "cns:core:price:discovery"; bytes32 public constant CNS_TREASURY = "cns:core:treasury"; 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_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_TOKEN = "ns:cover:reassurance:token"; bytes32 public constant NS_COVER_REASSURANCE_WEIGHT = "ns:cover:reassurance:weight"; bytes32 public constant NS_COVER_FEE_EARNING = "ns:cover:fee:earning"; bytes32 public constant NS_COVER_INFO = "ns:cover:info"; bytes32 public constant NS_COVER_OWNER = "ns:cover:owner"; 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_COVER_LIQUIDITY_LENDING_PERIOD = "ns:cover:liquidity:len:p"; 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_ADDED = "ns:cover:liquidity:add"; bytes32 public constant NS_COVER_LIQUIDITY_REMOVED = "ns:cover:liquidity:rem"; bytes32 public constant NS_COVER_LIQUIDITY_COMMITTED = "ns:cover:liquidity:committed"; bytes32 public constant NS_COVER_LIQUIDITY_NAME = "ns:cover:liquidityName"; bytes32 public constant NS_COVER_LIQUIDITY_RELEASE_DATE = "ns:cover:liquidity:release"; bytes32 public constant NS_COVER_REQUIRES_WHITELIST = "ns:cover:requires:whitelist"; bytes32 public constant NS_COVER_STABLECOIN_LENT_TOTAL = "ns:cover:sc:total:lent"; 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_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_COVER_PROVISION = "ns:cover:provision"; 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_COVER_CREATOR_WHITELIST = "ns:cover:creator:whitelist"; bytes32 public constant NS_COVER_USER_WHITELIST = "ns:cover:user:whitelist"; /// @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 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. /// 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"; /// @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_CLAIM_PLATFORM_FEE = "ns:claim: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_LP_RESERVE0 = "ns:uni:lp:reserve0"; bytes32 public constant NS_LP_RESERVE1 = "ns:uni:lp:reserve1"; bytes32 public constant NS_LP_TOTAL_SUPPLY = "ns:uni:lp:totalSupply"; bytes32 public constant NS_TOKEN_PRICE_LAST_UPDATE = "ns:token:price:last:update"; 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 = "PolicyAdmin"; bytes32 public constant CNAME_POLICY_MANAGER = "PolicyManager"; bytes32 public constant CNAME_BOND_POOL = "BondPool"; bytes32 public constant CNAME_STAKING_POOL = "StakingPool"; bytes32 public constant CNAME_POD_STAKING_POOL = "PODStakingPool"; bytes32 public constant CNAME_CLAIMS_PROCESSOR = "ClaimsProcessor"; bytes32 public constant CNAME_PRICE_DISCOVERY = "PriceDiscovery"; bytes32 public constant CNAME_COVER = "Cover"; bytes32 public constant CNAME_GOVERNANCE = "Governance"; bytes32 public constant CNAME_RESOLUTION = "Resolution"; bytes32 public constant CNAME_VAULT_FACTORY = "VaultFactory"; bytes32 public constant CNAME_CXTOKEN_FACTORY = "cxTokenFactory"; bytes32 public constant CNAME_COVER_PROVISION = "CoverProvision"; bytes32 public constant CNAME_COVER_STAKE = "CoverStake"; bytes32 public constant CNAME_COVER_REASSURANCE = "CoverReassurance"; bytes32 public constant CNAME_LIQUIDITY_VAULT = "Vault"; bytes32 public constant CNAME_VAULT_DELEGATE = "VaultDelegate"; bytes32 public constant CNAME_LIQUIDITY_ENGINE = "LiquidityEngine"; bytes32 public constant CNAME_STRATEGY_AAVE = "AaveStrategy"; bytes32 public constant CNAME_STRATEGY_COMPOUND = "CompoundStrategy"; function getProtocol(IStore s) external view returns (IProtocol) { return IProtocol(getProtocolAddress(s)); } function getProtocolAddress(IStore s) public view returns (address) { return s.getAddressByKey(CNS_CORE); } function getContract(IStore s, bytes32 name) external view returns (address) { return _getContract(s, name); } function isProtocolMember(IStore s, address contractAddress) external view returns (bool) { return _isProtocolMember(s, contractAddress); } /** * @dev Reverts if the caller is one of the protocol members. */ function mustBeProtocolMember(IStore s, address contractAddress) external view { bool isMember = _isProtocolMember(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, address sender ) public view { address contractAddress = _getContract(s, name); 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, caller); } function npmToken(IStore s) external view returns (IERC20) { return IERC20(getNpmTokenAddress(s)); } function getNpmTokenAddress(IStore s) public view returns (address) { address npm = s.getAddressByKey(CNS_NPM); return npm; } function getUniswapV2Router(IStore s) external view returns (address) { return s.getAddressByKey(CNS_UNISWAP_V2_ROUTER); } function getUniswapV2Factory(IStore s) external view returns (address) { return s.getAddressByKey(CNS_UNISWAP_V2_FACTORY); } function getTreasury(IStore s) external view returns (address) { return s.getAddressByKey(CNS_TREASURY); } function getReassuranceVault(IStore s) external view returns (address) { return s.getAddressByKey(CNS_REASSURANCE_VAULT); } function getStablecoin(IStore s) external view returns (address) { return s.getAddressByKey(CNS_COVER_STABLECOIN); } function getBurnAddress(IStore s) external view returns (address) { return s.getAddressByKey(CNS_BURNER); } function _isProtocolMember(IStore s, address contractAddress) private view returns (bool) { return s.getBoolByKeys(ProtoUtilV1.NS_MEMBERS, contractAddress); } function _getContract(IStore s, bytes32 name) private view returns (address) { return s.getAddressByKeys(NS_CONTRACTS, name); } }
/* 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; function ensureApproval( IERC20 malicious, address spender, uint256 amount ) external { // @suppress-address-trust-issue, @suppress-malicious-erc20 The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny. // @suppress-address-trust-issue The address `recipient` can be trusted as we're not treating (or calling) it as a contract. require(address(malicious) != address(0), "Invalid address"); require(spender != address(0), "Invalid spender"); require(amount > 0, "Invalid transfer amount"); malicious.safeIncreaseAllowance(spender, amount); } function ensureTransfer( IERC20 malicious, address recipient, uint256 amount ) external { // @suppress-address-trust-issue, @suppress-malicious-erc20 The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny. // @suppress-address-trust-issue The address `recipient` can be trusted as we're not treating (or calling) it as a contract. require(address(malicious) != address(0), "Invalid address"); require(recipient != address(0), "Invalid recipient"); 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"); } function ensureTransferFrom( IERC20 malicious, address sender, address recipient, uint256 amount ) external { // @suppress-address-trust-issue, @suppress-malicious-erc20 The address `malicious` can't be trusted and therefore we are ensuring that it does not act funny. // @suppress-address-trust-issue The address `recipient` can be trusted as we're not treating (or calling) it as a contract. require(address(malicious) != address(0), "Invalid address"); 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 (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; } }
// 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; } event ContractAdded(bytes32 namespace, bytes32 key, address contractAddress); event ContractUpgraded(bytes32 namespace, bytes32 key, address indexed previous, address indexed current); event MemberAdded(address member); event MemberRemoved(address member); function addContract(bytes32 namespace, address contractAddress) external; function addContractWithKey( bytes32 namespace, bytes32 key, address contractAddress ) external; function initialize(address[] memory addresses, uint256[] memory values) external; function upgradeContract( bytes32 namespace, address previous, address current ) external; function upgradeContractWithKey( bytes32 namespace, bytes32 key, address previous, address current ) external; function addMember(address member) external; function removeMember(address member) external; event Initialized(address[] addresses, uint256[] values); }
// 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, 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 memory value ) external { require(key > 0, "Invalid key"); s.setString(key, value); } function setStringByKeys( IStore s, bytes32 key1, bytes32 key2, string memory value ) external { return s.setString(_getKey(key1, key2), 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 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 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 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, 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 ) 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) { require(key1 > 0 && key2 > 0, "Invalid key(s)"); return keccak256(abi.encodePacked(key1, key2)); } function _getKey( bytes32 key1, bytes32 key2, bytes32 key3 ) private pure returns (bytes32) { require(key1 > 0 && key2 > 0 && key3 > 0, "Invalid key(s)"); return keccak256(abi.encodePacked(key1, key2, key3)); } function _getKey(bytes32 key, address account) private pure returns (bytes32) { require(key > 0 && account != address(0), "Invalid key(s)"); return keccak256(abi.encodePacked(key, account)); } function _getKey( bytes32 key1, bytes32 key2, address account ) private pure returns (bytes32) { require(key1 > 0 && key2 > 0 && account != address(0), "Invalid key(s)"); return keccak256(abi.encodePacked(key1, key2, account)); } }
// 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 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/IPriceDiscovery.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 getPriceDiscoveryContract(IStore s) external view returns (IPriceDiscovery) { return IPriceDiscovery(s.getContract(ProtoUtilV1.CNS_PRICE_DISCOVERY)); } function getGovernanceContract(IStore s) external view returns (IGovernance) { return IGovernance(s.getContract(ProtoUtilV1.CNS_GOVERNANCE)); } function getResolutionContract(IStore s) external view returns (IGovernance) { return IGovernance(s.getContract(ProtoUtilV1.CNS_GOVERNANCE_RESOLUTION)); } function getStakingContract(IStore s) external view returns (ICoverStake) { return ICoverStake(s.getContract(ProtoUtilV1.CNS_COVER_STAKE)); } function getCxTokenFactory(IStore s) external view returns (ICxTokenFactory) { return ICxTokenFactory(s.getContract(ProtoUtilV1.CNS_COVER_CXTOKEN_FACTORY)); } function getPolicyContract(IStore s) external view returns (IPolicy) { return IPolicy(s.getContract(ProtoUtilV1.CNS_COVER_POLICY)); } function getReassuranceContract(IStore s) external view returns (ICoverReassurance) { return ICoverReassurance(s.getContract(ProtoUtilV1.CNS_COVER_REASSURANCE)); } function getBondPoolContract(IStore s) external view returns (IBondPool) { return IBondPool(s.getContract(ProtoUtilV1.CNS_POOL_BOND)); } 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 key) external view returns (IVault) { return IVault(getVaultAddress(s, key)); } function getVaultAddress(IStore s, bytes32 key) public view returns (address) { address vault = getProtocolContract(s, ProtoUtilV1.CNS_COVER_VAULT, key); 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 vault = getProtocolContract(s, ProtoUtilV1.CNS_STAKING_POOL); return vault; } function getBondPoolAddress(IStore s, bytes32 key) external view returns (address) { address vault = getProtocolContract(s, ProtoUtilV1.CNS_BOND_POOL, key); return vault; } function getVaultFactoryContract(IStore s) external view returns (IVaultFactory) { address factory = s.getContract(ProtoUtilV1.CNS_COVER_VAULT_FACTORY); return IVaultFactory(factory); } }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "../interfaces/IStore.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./ProtoUtilV1.sol"; import "./AccessControlLibV1.sol"; import "./BokkyPooBahsDateTimeLibrary.sol"; import "./StoreKeyUtil.sol"; import "./RegistryLibV1.sol"; import "./NTransferUtilV2.sol"; import "./StrategyLibV1.sol"; import "../interfaces/ICxToken.sol"; library CoverUtilV1 { using RegistryLibV1 for IStore; using ProtoUtilV1 for IStore; using StoreKeyUtil for IStore; using AccessControlLibV1 for IStore; using NTransferUtilV2 for IERC20; using StrategyLibV1 for IStore; enum CoverStatus { Normal, Stopped, IncidentHappened, FalseReporting, Claimable } function getCoverOwner(IStore s, bytes32 key) external view returns (address) { return _getCoverOwner(s, key); } function _getCoverOwner(IStore s, bytes32 key) private view returns (address) { return s.getAddressByKeys(ProtoUtilV1.NS_COVER_OWNER, key); } function getCoverFee(IStore s) external view returns ( uint256 fee, uint256 minCoverCreationStake, uint256 minStakeToAddLiquidity ) { fee = s.getUintByKey(ProtoUtilV1.NS_COVER_CREATION_FEE); minCoverCreationStake = getMinCoverCreationStake(s); minStakeToAddLiquidity = getMinStakeToAddLiquidity(s); } function getMinCoverCreationStake(IStore s) public view returns (uint256) { uint256 value = s.getUintByKey(ProtoUtilV1.NS_COVER_CREATION_MIN_STAKE); if (value == 0) { // Fallback to 250 NPM value = 250 ether; } return value; } function getMinStakeToAddLiquidity(IStore s) public view returns (uint256) { uint256 value = s.getUintByKey(ProtoUtilV1.NS_COVER_LIQUIDITY_MIN_STAKE); if (value == 0) { // Fallback to 250 NPM value = 250 ether; } return value; } function getClaimPeriod(IStore s, bytes32 key) external view returns (uint256) { uint256 fromKey = s.getUintByKeys(ProtoUtilV1.NS_CLAIM_PERIOD, key); uint256 fallbackValue = s.getUintByKey(ProtoUtilV1.NS_CLAIM_PERIOD); return fromKey > 0 ? fromKey : fallbackValue; } /** * @dev Returns the values of the given cover key * @param _values[0] The total amount in the cover pool * @param _values[1] The total commitment amount * @param _values[2] The total amount of NPM provision * @param _values[3] NPM price * @param _values[4] The total amount of reassurance tokens * @param _values[5] Reassurance token price * @param _values[6] Reassurance pool weight */ function getCoverPoolSummaryInternal(IStore s, bytes32 key) external view returns (uint256[] memory _values) { IPriceDiscovery discovery = s.getPriceDiscoveryContract(); _values = new uint256[](7); _values[0] = s.getStablecoinOwnedByVaultInternal(key); _values[1] = getActiveLiquidityUnderProtection(s, key); _values[2] = s.getUintByKeys(ProtoUtilV1.NS_COVER_PROVISION, key); _values[3] = discovery.getTokenPriceInStableCoin(address(s.npmToken()), 1 ether); _values[4] = s.getUintByKeys(ProtoUtilV1.NS_COVER_REASSURANCE, key); _values[5] = discovery.getTokenPriceInStableCoin(address(s.getAddressByKeys(ProtoUtilV1.NS_COVER_REASSURANCE_TOKEN, key)), 1 ether); _values[6] = s.getUintByKeys(ProtoUtilV1.NS_COVER_REASSURANCE_WEIGHT, key); } /** * @dev Gets 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 getCoverStatus(IStore s, bytes32 key) external view returns (CoverStatus) { return CoverStatus(getStatus(s, key)); } function getCoverStatusOf( IStore s, bytes32 key, uint256 incidentDate ) external view returns (CoverStatus) { return CoverStatus(getStatusOf(s, key, incidentDate)); } function getStatus(IStore s, bytes32 key) public view returns (uint256) { return s.getUintByKey(getCoverStatusKey(key)); } function getStatusOf( IStore s, bytes32 key, uint256 incidentDate ) public view returns (uint256) { return s.getUintByKey(getCoverStatusOfKey(key, incidentDate)); } function getCoverStatusKey(bytes32 key) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_STATUS, key)); } function getCoverStatusOfKey(bytes32 key, uint256 incidentDate) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_STATUS, key, incidentDate)); } function getCoverLiquidityAddedKey(bytes32 coverKey, address account) external pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_ADDED, coverKey, account)); } function getCoverLiquidityReleaseDateKey(bytes32 coverKey, address account) external pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_RELEASE_DATE, coverKey, account)); } function getCoverLiquidityStakeKey(bytes32 coverKey) external pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_STAKE, coverKey)); } function getCoverLiquidityStakeIndividualKey(bytes32 coverKey, address account) external pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_STAKE, coverKey, account)); } function getCoverTotalLentKey(bytes32 coverKey) external pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_STABLECOIN_LENT_TOTAL, coverKey)); } function getActiveLiquidityUnderProtection(IStore s, bytes32 key) public view returns (uint256) { (uint256 current, uint256 future) = _getLiquidityUnderProtectionInfo(s, key); return current + future; } function _getLiquidityUnderProtectionInfo(IStore s, bytes32 key) private view returns (uint256 current, uint256 future) { uint256 expiryDate = 0; (current, expiryDate) = _getCurrentCommitment(s, key); future = _getFutureCommitments(s, key, expiryDate); } function _getCurrentCommitment(IStore s, bytes32 key) private view returns (uint256 amount, uint256 expiryDate) { uint256 incidentDateIfAny = getActiveIncidentDateInternal(s, key); // 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, key, expiryDate)); if (address(cxToken) != address(0)) { amount = cxToken.totalSupply(); } } function _getFutureCommitments( IStore s, bytes32 key, uint256 ignoredExpiryDate ) private view returns (uint256 sum) { uint256 maxMonthsToProtect = 3; for (uint256 i = 0; i < maxMonthsToProtect; i++) { uint256 expiryDate = _getNextMonthEndDate(block.timestamp, i); // solhint-disable-line if (expiryDate == ignoredExpiryDate || expiryDate <= block.timestamp) { // solhint-disable-previous-line continue; } ICxToken cxToken = ICxToken(getCxTokenByExpiryDateInternal(s, key, expiryDate)); if (address(cxToken) != address(0)) { sum += cxToken.totalSupply(); } } } function getStake(IStore s, bytes32 key) external view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_COVER_STAKE, key); } /** * @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 key, uint256 incidentDate, CoverStatus status ) external { s.setUintByKey(getCoverStatusKey(key), uint256(status)); if (incidentDate > 0) { s.setUintByKey(getCoverStatusOfKey(key, incidentDate), uint256(status)); } } /** * @dev Gets the reassurance amount of the specified cover contract * @param key Enter the cover key */ function getReassuranceAmountInternal(IStore s, bytes32 key) external view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_COVER_REASSURANCE, key); } /** * @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); } function getActiveIncidentDateInternal(IStore s, bytes32 key) public view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_INCIDENT_DATE, key); } function getCxTokenByExpiryDateInternal( IStore s, bytes32 key, uint256 expiryDate ) public view returns (address cxToken) { bytes32 k = keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_CXTOKEN, key, expiryDate)); cxToken = s.getAddress(k); } function checkIfRequiresWhitelist(IStore s, bytes32 key) external view returns (bool) { return s.getBoolByKeys(ProtoUtilV1.NS_COVER_REQUIRES_WHITELIST, key); } }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "../interfaces/IStore.sol"; import "../interfaces/IPolicy.sol"; import "../interfaces/ICoverStake.sol"; import "../interfaces/IPriceDiscovery.sol"; import "../interfaces/ICoverReassurance.sol"; import "../interfaces/IVault.sol"; import "../interfaces/IVaultFactory.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./ProtoUtilV1.sol"; import "./RoutineInvokerLibV1.sol"; import "./StoreKeyUtil.sol"; import "./CoverUtilV1.sol"; library GovernanceUtilV1 { using CoverUtilV1 for IStore; using StoreKeyUtil for IStore; using ProtoUtilV1 for IStore; using RoutineInvokerLibV1 for IStore; function getReportingPeriod(IStore s, bytes32 key) external view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_PERIOD, key); } function getReportingBurnRate(IStore s) public view returns (uint256) { return s.getUintByKey(ProtoUtilV1.NS_GOVERNANCE_REPORTING_BURN_RATE); } function getGovernanceReporterCommission(IStore s) public view returns (uint256) { return s.getUintByKey(ProtoUtilV1.NS_GOVERNANCE_REPORTER_COMMISSION); } function getClaimPlatformFee(IStore s) external view returns (uint256) { return s.getUintByKey(ProtoUtilV1.NS_CLAIM_PLATFORM_FEE); } function getClaimReporterCommission(IStore s) external view returns (uint256) { return s.getUintByKey(ProtoUtilV1.NS_CLAIM_REPORTER_COMMISSION); } function getMinReportingStake(IStore s, bytes32 key) external view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_MIN_FIRST_STAKE, key); } function getLatestIncidentDate(IStore s, bytes32 key) external view returns (uint256) { return _getLatestIncidentDate(s, key); } function getResolutionTimestamp(IStore s, bytes32 key) external view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_RESOLUTION_TS, key); } function getReporter( IStore s, bytes32 key, uint256 incidentDate ) external view returns (address) { CoverUtilV1.CoverStatus status = CoverUtilV1.getCoverStatusOf(s, key, incidentDate); bool incidentHappened = status == CoverUtilV1.CoverStatus.IncidentHappened || status == CoverUtilV1.CoverStatus.Claimable; bytes32 prefix = incidentHappened ? ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES : ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO; return s.getAddressByKeys(prefix, key); } function getStakes( IStore s, bytes32 key, uint256 incidentDate ) public view returns (uint256 yes, uint256 no) { yes = s.getUintByKey(getIncidentOccurredStakesKey(key, incidentDate)); no = s.getUintByKey(getFalseReportingStakesKey(key, incidentDate)); } function getReporterKey(bytes32 key) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES, key)); } function getIncidentOccurredStakesKey(bytes32 key, uint256 incidentDate) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_YES, key, incidentDate)); } function getIndividualIncidentOccurredStakeKey( bytes32 key, uint256 incidentDate, address account ) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_STAKE_OWNED_YES, key, incidentDate, account)); } function getDisputerKey(bytes32 key) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO, key)); } function getFalseReportingStakesKey(bytes32 key, uint256 incidentDate) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_WITNESS_NO, key, incidentDate)); } function getIndividualFalseReportingStakeKey( bytes32 key, uint256 incidentDate, address account ) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_STAKE_OWNED_NO, key, incidentDate, account)); } function getStakesOf( IStore s, address account, bytes32 key, uint256 incidentDate ) public view returns (uint256 yes, uint256 no) { yes = s.getUintByKey(getIndividualIncidentOccurredStakeKey(key, incidentDate, account)); no = s.getUintByKey(getIndividualFalseReportingStakeKey(key, incidentDate, account)); } function getResolutionInfoFor( IStore s, address account, bytes32 key, uint256 incidentDate ) public view returns ( uint256 totalStakeInWinningCamp, uint256 totalStakeInLosingCamp, uint256 myStakeInWinningCamp ) { (uint256 yes, uint256 no) = getStakes(s, key, incidentDate); (uint256 myYes, uint256 myNo) = getStakesOf(s, account, key, incidentDate); CoverUtilV1.CoverStatus decision = CoverUtilV1.getCoverStatusOf(s, key, incidentDate); bool incidentHappened = decision == CoverUtilV1.CoverStatus.IncidentHappened || decision == CoverUtilV1.CoverStatus.Claimable; totalStakeInWinningCamp = incidentHappened ? yes : no; totalStakeInLosingCamp = incidentHappened ? no : yes; myStakeInWinningCamp = incidentHappened ? myYes : myNo; } function getUnstakeInfoForInternal( IStore s, address account, bytes32 key, uint256 incidentDate ) external view returns ( uint256 totalStakeInWinningCamp, uint256 totalStakeInLosingCamp, uint256 myStakeInWinningCamp, uint256 toBurn, uint256 toReporter, uint256 myReward, uint256 unstaken ) { (totalStakeInWinningCamp, totalStakeInLosingCamp, myStakeInWinningCamp) = getResolutionInfoFor(s, account, key, incidentDate); unstaken = getReportingUnstakenAmount(s, account, key, incidentDate); require(myStakeInWinningCamp > 0, "Nothing to unstake"); uint256 rewardRatio = (myStakeInWinningCamp * ProtoUtilV1.MULTIPLIER) / 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 (_getLatestIncidentDate(s, key) == incidentDate) { // slither-disable-next-line divide-before-multiply reward = (totalStakeInLosingCamp * rewardRatio) / ProtoUtilV1.MULTIPLIER; } toBurn = (reward * getReportingBurnRate(s)) / ProtoUtilV1.MULTIPLIER; toReporter = (reward * getGovernanceReporterCommission(s)) / ProtoUtilV1.MULTIPLIER; myReward = reward - toBurn - toReporter; } function getReportingUnstakenAmount( IStore s, address account, bytes32 key, uint256 incidentDate ) public view returns (uint256) { bytes32 k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_TS, key, incidentDate, account)); k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, key, incidentDate, account)); return s.getUintByKey(k); } function updateUnstakeDetails( IStore s, address account, bytes32 key, 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, key, incidentDate, account)); s.setUintByKey(k, block.timestamp); // solhint-disable-line // Last unstake timestamp k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_TS, key, incidentDate)); s.setUintByKey(k, block.timestamp); // solhint-disable-line // --------------------------------------------------------------------- // Amount unstaken by the account k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, key, incidentDate, account)); s.setUintByKey(k, originalStake); // Amount unstaken by everyone k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKEN, key, incidentDate)); s.addUintByKey(k, originalStake); // --------------------------------------------------------------------- if (reward > 0) { // Reward received by the account k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_REWARD, key, incidentDate, account)); s.setUintByKey(k, reward); // Total reward received k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_REWARD, key, incidentDate)); s.addUintByKey(k, reward); } // --------------------------------------------------------------------- if (burned > 0) { // Total burned k = keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_UNSTAKE_BURNED, key, 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, key, incidentDate)); s.addUintByKey(k, reporterFee); } } function updateCoverStatusBeforeResolution( IStore s, bytes32 key, uint256 incidentDate ) public { require(incidentDate > 0, "Invalid incident date"); uint256 yes = s.getUintByKey(getIncidentOccurredStakesKey(key, incidentDate)); uint256 no = s.getUintByKey(getFalseReportingStakesKey(key, incidentDate)); if (no > yes) { s.setStatusInternal(key, incidentDate, CoverUtilV1.CoverStatus.FalseReporting); return; } s.setStatusInternal(key, incidentDate, CoverUtilV1.CoverStatus.IncidentHappened); } function addAttestation( IStore s, bytes32 key, address who, uint256 incidentDate, uint256 stake ) external { // @suppress-address-trust-issue The address `who` can be trusted here because we are not performing any direct calls to it. // Add individual stake of the reporter s.addUintByKey(getIndividualIncidentOccurredStakeKey(key, incidentDate, who), stake); // All "incident happened" camp witnesses combined uint256 currentStake = s.getUintByKey(getIncidentOccurredStakesKey(key, incidentDate)); // No has reported yet, this is the first report if (currentStake == 0) { s.setAddressByKey(getReporterKey(key), msg.sender); } s.addUintByKey(getIncidentOccurredStakesKey(key, incidentDate), stake); updateCoverStatusBeforeResolution(s, key, incidentDate); s.updateStateAndLiquidity(key); } function getAttestation( IStore s, bytes32 key, address who, uint256 incidentDate ) external view returns (uint256 myStake, uint256 totalStake) { myStake = s.getUintByKey(getIndividualIncidentOccurredStakeKey(key, incidentDate, who)); totalStake = s.getUintByKey(getIncidentOccurredStakesKey(key, incidentDate)); } function addDispute( IStore s, bytes32 key, address who, uint256 incidentDate, uint256 stake ) external { // @suppress-address-trust-issue The address `who` can be trusted here because we are not performing any direct calls to it. s.addUintByKey(getIndividualFalseReportingStakeKey(key, incidentDate, who), stake); uint256 currentStake = s.getUintByKey(getFalseReportingStakesKey(key, incidentDate)); if (currentStake == 0) { // The first reporter who disputed s.setAddressByKey(getDisputerKey(key), msg.sender); s.setBoolByKey(getHasDisputeKey(key), true); } s.addUintByKey(getFalseReportingStakesKey(key, incidentDate), stake); updateCoverStatusBeforeResolution(s, key, incidentDate); s.updateStateAndLiquidity(key); } function getHasDisputeKey(bytes32 key) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_GOVERNANCE_REPORTING_HAS_A_DISPUTE, key)); } function getDispute( IStore s, bytes32 key, address who, uint256 incidentDate ) external view returns (uint256 myStake, uint256 totalStake) { myStake = s.getUintByKey(getIndividualFalseReportingStakeKey(key, incidentDate, who)); totalStake = s.getUintByKey(getFalseReportingStakesKey(key, incidentDate)); } function _getLatestIncidentDate(IStore s, bytes32 key) private view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_GOVERNANCE_REPORTING_INCIDENT_DATE, key); } function getCoolDownPeriodInternal(IStore s, bytes32 key) external view returns (uint256) { uint256 fromKey = s.getUintByKeys(ProtoUtilV1.NS_RESOLUTION_COOL_DOWN_PERIOD, key); uint256 fallbackValue = s.getUintByKey(ProtoUtilV1.NS_RESOLUTION_COOL_DOWN_PERIOD); return fromKey > 0 ? fromKey : fallbackValue; } function getResolutionDeadlineInternal(IStore s, bytes32 key) public view returns (uint256) { return s.getUintByKeys(ProtoUtilV1.NS_RESOLUTION_DEADLINE, key); } function isResolvedInternal(IStore s, bytes32 key) external view returns (bool) { return getResolutionDeadlineInternal(s, key) > block.timestamp; // solhint-disable-line } }
// 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 sender is not the protocol admin. */ function callerMustBeAdmin(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_ADMIN, caller); } /** * @dev Reverts if the sender is not the cover manager. */ function callerMustBeCoverManager(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_COVER_MANAGER, caller); } /** * @dev Reverts if the sender is not the liquidity manager. */ function callerMustBeLiquidityManager(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_LIQUIDITY_MANAGER, caller); } /** * @dev Reverts if the sender is not a governance agent. */ function callerMustBeGovernanceAgent(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_GOVERNANCE_AGENT, caller); } /** * @dev Reverts if the sender is not a governance admin. */ function callerMustBeGovernanceAdmin(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_GOVERNANCE_ADMIN, caller); } /** * @dev Reverts if the sender is not an upgrade agent. */ function callerMustBeUpgradeAgent(IStore s, address caller) public view { _mustHaveAccess(s, NS_ROLES_UPGRADE_AGENT, caller); } /** * @dev Reverts if the sender is not a recovery agent. */ function callerMustBeRecoveryAgent(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_RECOVERY_AGENT, caller); } /** * @dev Reverts if the sender is not the pause agent. */ function callerMustBePauseAgent(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_PAUSE_AGENT, caller); } /** * @dev Reverts if the sender is not the unpause agent. */ function callerMustBeUnpauseAgent(IStore s, address caller) external view { _mustHaveAccess(s, NS_ROLES_UNPAUSE_AGENT, caller); } /** * @dev Reverts if the sender does not have access to the given role. */ function _mustHaveAccess( IStore s, bytes32 role, address caller ) private view { require(hasAccess(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 hasAccess( IStore s, bytes32 role, address user ) public view returns (bool) { address protocol = s.getProtocolAddress(); // 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); } 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)); // @suppress-address-trust-issue This feature can only be accessed internally within the protocol. _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); } 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)); // @suppress-address-trust-issue This feature can only be accessed internally within the protocol. bool isMember = s.isProtocolMember(previous); require(isMember, "Not a protocol member"); _deleteContract(s, namespace, key, previous); _addContract(s, namespace, key, current); } 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)); // @suppress-address-trust-issue This feature can only be accessed internally within the protocol. _addMember(s, 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)); // @suppress-address-trust-issue This feature can only be accessed internally within the protocol. _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; interface IPausable { function paused() external view returns (bool); }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "./IMember.sol"; interface ICover is IMember { event CoverCreated(bytes32 key, bytes32 info, bool requiresWhitelist); event CoverUpdated(bytes32 key, bytes32 info); event CoverStopped(bytes32 indexed coverKey, address indexed deletedBy, string reason); event VaultDeployed(bytes32 indexed coverKey, address vault); event CoverCreatorWhitelistUpdated(address account, bool status); event CoverUserWhitelistUpdated(bytes32 key, address account, bool status); event CoverFeeSet(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 liquidityToken Provide the address of the token this cover will be quoted against. * @param liquidityName Enter a description or ENS name of your liquidity token. * */ function initialize(address liquidityToken, bytes32 liquidityName) 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 * * @param key Enter a unique key for this cover * @param info IPFS info of the cover contract * @param reassuranceToken **Optional.** Token added as an reassurance of this cover. <br /><br /> * * Reassurance tokens can be added by a project to demonstrate coverage support * for their own project. This helps bring the cover fee down and enhances * liquidity provider confidence. Along with the NPM tokens, the reassurance tokens are rewarded * as a support to the liquidity providers when a cover incident occurs. * @param values[0] stakeWithFee Enter the total NPM amount (stake + fee) to transfer to this contract. * @param values[1] initialReassuranceAmount **Optional.** Enter the initial amount of * @param values[2] minStakeToReport A cover creator can override default min NPM stake to avoid spam reports * @param values[3] reportingPeriod The period during when reporting happens. * reassurance tokens you'd like to add to this pool. * @param values[4] cooldownperiod Enter the cooldown period for governance. * @param values[5] claimPeriod Enter the claim period. * @param values[6] floor Enter the policy floor rate. * @param values[7] ceiling Enter the policy ceiling rate. */ function addCover( bytes32 key, bytes32 info, address reassuranceToken, bool requiresWhitelist, uint256[] memory values ) external; function deployVault(bytes32 key) external returns (address); /** * @dev Updates the cover contract. * This feature is accessible only to the cover owner or protocol owner (governance). * * @param key Enter the cover key * @param info Enter a new IPFS URL to update */ function updateCover(bytes32 key, bytes32 info) external; function updateCoverCreatorWhitelist(address account, bool whitelisted) external; function updateCoverUsersWhitelist( bytes32 key, address[] memory accounts, bool[] memory statuses ) external; /** * @dev Get info of a cover contract by key * @param key Enter the cover key * @param coverOwner Returns the address of the cover creator * @param info Gets the IPFS hash of the cover info * @param values Array of uint256 values. See `CoverUtilV1.getCoverInfo`. */ function getCover(bytes32 key) external view returns ( address coverOwner, bytes32 info, uint256[] memory values ); function stopCover(bytes32 key, string memory reason) external; function checkIfWhitelistedCoverCreator(address account) external view returns (bool); function checkIfWhitelistedUser(bytes32 key, address account) external view returns (bool); function setCoverFees(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 IPolicy is IMember { event CoverPurchased(bytes32 key, address indexed account, address indexed cxToken, uint256 fee, uint256 amountToCover, uint256 expiresOn); /** * @dev Purchase cover for the specified amount. <br /> <br /> * When you purchase covers, you recieve 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. * @param key Enter the cover key you wish to purchase the policy for * @param coverDuration Enter the number of months to cover. Accepted values: 1-3. * @param amountToCover Enter the amount of the stablecoin `liquidityToken` to cover. */ function purchaseCover( bytes32 key, uint256 coverDuration, uint256 amountToCover ) external returns (address); /** * @dev Gets the cover fee info for the given cover key, duration, and amount * @param key Enter the cover key * @param coverDuration Enter the number of months to cover. Accepted values: 1-3. * @param amountToCover Enter the amount of the stablecoin `liquidityToken` to cover. */ function getCoverFeeInfo( bytes32 key, uint256 coverDuration, uint256 amountToCover ) external view returns ( uint256 fee, uint256 utilizationRatio, uint256 totalAvailableLiquidity, uint256 coverRatio, uint256 floor, uint256 ceiling, uint256 rate ); /** * @dev Returns the values of the given cover key * @param _values[0] The total amount in the cover pool * @param _values[1] The total commitment amount * @param _values[2] The total amount of NPM provision * @param _values[3] NPM price * @param _values[4] The total amount of reassurance tokens * @param _values[5] Reassurance token price * @param _values[6] Reassurance pool weight */ function getCoverPoolSummary(bytes32 key) external view returns (uint256[] memory _values); function getCxToken(bytes32 key, uint256 coverDuration) external view returns (address cxToken, uint256 expiryDate); function getCxTokenByExpiryDate(bytes32 key, uint256 expiryDate) external view returns (address cxToken); /** * Gets the sum total of cover commitment that haven't expired yet. */ function getCommitment(bytes32 key) external view returns (uint256); /** * Gets the available liquidity in the pool. */ function getAvailableLiquidity(bytes32 key) 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 IBondPool is IMember { event BondPoolSetup(address[] addresses, uint256[] values); event BondCreated(address indexed account, uint256 lpTokens, uint256 npmToVest, uint256 unlockDate); event BondClaimed(address indexed account, uint256 amount); function setup(address[] memory addresses, uint256[] memory values) 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 (address[] memory addresses, uint256[] memory values); }
// 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 key, uint256 amount); event StakeRemoved(bytes32 key, uint256 amount); event FeeBurned(bytes32 key, uint256 amount); /** * @dev Increase the stake of the given cover pool * @param key 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 key, address account, uint256 amount, uint256 fee ) external; /** * @dev Decreases the stake from the given cover pool * @param key Enter the cover key * @param account Enter the account to decrease the stake of * @param amount Enter the amount of stake to decrease */ function decreaseStake( bytes32 key, address account, uint256 amount ) external; /** * @dev Gets the stake of an account for the given cover key * @param key 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 key, address account) external view returns (uint256); }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; import "./IMember.sol"; interface IPriceDiscovery is IMember { function getTokenPriceInStableCoin(address token, uint256 multiplier) external view returns (uint256); function getTokenPriceInLiquidityToken( address token, address liquidityToken, uint256 multiplier ) external view returns (uint256); }
// 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 key, uint256 amount); /** * @dev Adds reassurance to the specified cover contract * @param key Enter the cover key * @param amount Enter the amount you would like to supply */ function addReassurance( bytes32 key, address account, uint256 amount ) external; function setWeight(bytes32 key, uint256 weight) external; /** * @dev Gets the reassurance amount of the specified cover contract * @param key Enter the cover key */ function getReassurance(bytes32 key) external view returns (uint256); }
// 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"; interface IGovernance is IMember, IReporter, IWitness {}
// 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(bytes32 indexed key, address vault); function deploy(IStore s, bytes32 key) external returns (address); }
// Neptune Mutual Protocol (https://neptunemutual.com) // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.0; interface IReporter { event Reported(bytes32 indexed key, address indexed reporter, uint256 incidentDate, bytes32 info, uint256 initialStake, uint256 resolutionTimestamp); event Disputed(bytes32 indexed key, address indexed reporter, uint256 incidentDate, bytes32 info, uint256 initialStake); event ReportingBurnRateSet(uint256 previous, uint256 current); event FirstReportingStakeSet(uint256 previous, uint256 current); event ReporterCommissionSet(uint256 previous, uint256 current); function report( bytes32 key, bytes32 info, uint256 stake ) external; function dispute( bytes32 key, uint256 incidentDate, bytes32 info, uint256 stake ) external; function getActiveIncidentDate(bytes32 key) external view returns (uint256); function getReporter(bytes32 key, uint256 incidentDate) external view returns (address); function getResolutionDate(bytes32 key) external view returns (uint256); function setFirstReportingStake(uint256 value) external; function getFirstReportingStake() external view returns (uint256); function getFirstReportingStake(bytes32 key) 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 key, address indexed witness, uint256 incidentDate, uint256 stake); event Refuted(bytes32 indexed key, address indexed witness, uint256 incidentDate, uint256 stake); function attest( bytes32 key, uint256 incidentDate, uint256 stake ) external; function refute( bytes32 key, uint256 incidentDate, uint256 stake ) external; function getStatus(bytes32 key) external view returns (uint256); function getStakes(bytes32 key, uint256 incidentDate) external view returns (uint256, uint256); function getStakesOf( bytes32 key, uint256 incidentDate, address account ) external view returns (uint256, uint256); }
/* solhint-disable 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 "./ProtoUtilV1.sol"; import "./NTransferUtilV2.sol"; library StrategyLibV1 { using NTransferUtilV2 for IERC20; using ProtoUtilV1 for IStore; using StoreKeyUtil for IStore; using RegistryLibV1 for IStore; event StrategyAdded(address indexed strategy); function _getIsActiveStrategyKey(address strategyAddress) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_ACTIVE, strategyAddress)); } function disableStrategyInternal(IStore s, address toFind) external { // @suppress-address-trust-issue Check caller. _deleteStrategy(s, toFind); s.setAddressArrayByKey(ProtoUtilV1.NS_LENDING_STRATEGY_DISABLED, toFind); } function addStrategiesInternal(IStore s, address[] memory strategies) external { for (uint256 i = 0; i < strategies.length; i++) { address strategy = strategies[i]; _addStrategy(s, strategy); } } function getLendingPeriodsInternal(IStore s, bytes32 coverKey) external view returns (uint256 lendingPeriod, uint256 withdrawalWindow) { lendingPeriod = s.getUintByKey(getLendingPeriodKey(coverKey, true)); withdrawalWindow = s.getUintByKey(getWithdrawalWindowKey(coverKey, true)); if (lendingPeriod == 0) { lendingPeriod = s.getUintByKey(getLendingPeriodKey(0, true)); withdrawalWindow = s.getUintByKey(getWithdrawalWindowKey(0, true)); } } function setLendingPeriodsInternal( IStore s, bytes32 coverKey, uint256 lendingPeriod, uint256 withdrawalWindow ) external { s.setUintByKey(getLendingPeriodKey(coverKey, true), lendingPeriod); s.setUintByKey(getWithdrawalWindowKey(coverKey, true), withdrawalWindow); } function getLendingPeriodKey(bytes32 coverKey, bool ignoreMissingKey) public pure returns (bytes32) { if (ignoreMissingKey == false) { require(coverKey > 0, "Invalid Cover Key"); } if (coverKey > 0) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_LIQUIDITY_LENDING_PERIOD, coverKey)); } return ProtoUtilV1.NS_COVER_LIQUIDITY_LENDING_PERIOD; } function getWithdrawalWindowKey(bytes32 coverKey, bool ignoreMissingKey) public pure returns (bytes32) { if (ignoreMissingKey == false) { require(coverKey > 0, "Invalid Cover Key"); } 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 _deleteStrategy(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); } 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); } function getStrategyOutKey(bytes32 coverKey, address token) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_STRATEGY_OUT, coverKey, token)); } function getSpecificStrategyOutKey( bytes32 coverKey, bytes32 strategyName, address token ) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_VAULT_STRATEGY_OUT, coverKey, strategyName, token)); } function getAmountInStrategies( IStore s, bytes32 coverKey, address token ) public view returns (uint256) { bytes32 k = getStrategyOutKey(coverKey, token); return s.getUintByKey(k); } function getAmountInStrategy( IStore s, bytes32 coverKey, bytes32 strategyName, address token ) public view returns (uint256) { bytes32 k = getSpecificStrategyOutKey(coverKey, strategyName, token); return s.getUintByKey(k); } function preTransferToStrategyInternal( IStore s, IERC20 token, bytes32 coverKey, bytes32 strategyName, uint256 amount ) external { bool isStablecoin = s.getStablecoin() == address(token) ? true : false; if (isStablecoin == false) { 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 toReceive ) external returns (uint256 income, uint256 loss) { bool isStablecoin = s.getStablecoin() == address(token) ? true : false; if (isStablecoin == false) { return (income, loss); } uint256 amountInThisStrategy = getAmountInStrategy(s, coverKey, strategyName, address(token)); income = toReceive > amountInThisStrategy ? toReceive - amountInThisStrategy : 0; loss = toReceive < amountInThisStrategy ? amountInThisStrategy - toReceive : 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 = getStrategyOutKey(coverKey, token); s.addUintByKey(k, amountToAdd); } function _reduceStrategyOut( IStore s, bytes32 coverKey, address token, uint256 amount ) private { bytes32 k = getStrategyOutKey(coverKey, token); s.subtractUintByKey(k, amount); } function _addToSpecificStrategyOut( IStore s, bytes32 coverKey, bytes32 strategyName, address token, uint256 amountToAdd ) private { bytes32 k = getSpecificStrategyOutKey(coverKey, strategyName, token); s.addUintByKey(k, amountToAdd); } function _clearSpecificStrategyOut( IStore s, bytes32 coverKey, bytes32 strategyName, address token ) private { bytes32 k = getSpecificStrategyOutKey(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) public view returns (uint256) { address stablecoin = s.getStablecoin(); uint256 balance = IERC20(stablecoin).balanceOf(s.getVaultAddress(coverKey)); uint256 inStrategies = getAmountInStrategies(s, coverKey, stablecoin); return balance + inStrategies; } }
// 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"); } } }
// 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); } } } }
// 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 { event Deposited(bytes32 indexed key, address indexed onBehalfOf, uint256 stablecoinDeposited); event Withdrawn(bytes32 indexed key, address indexed sendTo, uint256 stablecoinWithdrawn); 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 * @param values[0] deposits Total amount deposited * @param values[1] withdrawals Total amount withdrawn */ function getInfo(bytes32 coverKey) external view returns (uint256[] memory values); 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/external/IUniswapV2RouterLike.sol"; import "../interfaces/external/IUniswapV2PairLike.sol"; import "../interfaces/external/IUniswapV2FactoryLike.sol"; import "./NTransferUtilV2.sol"; import "./ProtoUtilV1.sol"; import "./StoreKeyUtil.sol"; import "./ValidationLibV1.sol"; import "./RegistryLibV1.sol"; // @todo: use an oracle service library PriceLibV1 { using ProtoUtilV1 for IStore; using StoreKeyUtil for IStore; uint256 public constant UPDATE_INTERVAL = 15 minutes; function setTokenPriceInStablecoinInternal(IStore s, address token) internal { if (token == address(0)) { return; } address stablecoin = s.getStablecoin(); setTokenPriceInternal(s, token, stablecoin); } function setTokenPriceInternal( IStore s, address token, address stablecoin ) internal { IUniswapV2PairLike pair = _getPair(s, token, stablecoin); _setTokenPrice(s, token, stablecoin, pair); } /** * @dev Returns the last persisted pair info * @param s Provide store instance * @param pair Provide pair instance * @param values[0] reserve0 * @param values[1] reserve1 * @param values[2] totalSupply */ function getLastKnownPairInfoInternal(IStore s, IUniswapV2PairLike pair) public view returns (uint256[] memory values) { values = new uint256[](3); values[0] = s.getUintByKey(_getReserve0Key(pair)); values[1] = s.getUintByKey(_getReserve1Key(pair)); values[2] = s.getUintByKey(_getPairTotalSupplyKey(pair)); } function _setTokenPrice( IStore s, address token, address stablecoin, IUniswapV2PairLike pair ) private { if (token == stablecoin) { return; } // solhint-disable-next-line if (getLastUpdateOnInternal(s, token, stablecoin) + UPDATE_INTERVAL > block.timestamp) { return; } (uint112 reserve0, uint112 reserve1, ) = pair.getReserves(); s.setUintByKey(_getReserve0Key(pair), reserve0); s.setUintByKey(_getReserve1Key(pair), reserve1); s.setUintByKey(_getPairTotalSupplyKey(pair), pair.totalSupply()); _setLastUpdateOn(s, token, stablecoin); } function getPairLiquidityInStablecoin( IStore s, IUniswapV2PairLike pair, uint256 lpTokens ) external view returns (uint256) { uint256[] memory values = getLastKnownPairInfoInternal(s, pair); uint256 reserve0 = values[0]; uint256 reserve1 = values[1]; uint256 supply = values[2]; address stablecoin = s.getStablecoin(); if (pair.token0() == stablecoin) { return (2 * reserve0 * lpTokens) / supply; } return (2 * reserve1 * lpTokens) / supply; } function getLastUpdateOnInternal( IStore s, address token, address liquidityToken ) public view returns (uint256) { bytes32 key = _getLastUpdateKey(token, liquidityToken); return s.getUintByKey(key); } function _setLastUpdateOn( IStore s, address token, address liquidityToken ) private { bytes32 key = _getLastUpdateKey(token, liquidityToken); s.setUintByKey(key, block.timestamp); // solhint-disable-line } function _getLastUpdateKey(address token0, address token1) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_TOKEN_PRICE_LAST_UPDATE, token0, token1)); } function getPriceInternal( IStore s, address token, address stablecoin, uint256 multiplier ) public view returns (uint256) { IUniswapV2PairLike pair = _getPair(s, token, stablecoin); IUniswapV2RouterLike router = IUniswapV2RouterLike(s.getUniswapV2Router()); uint256[] memory values = getLastKnownPairInfoInternal(s, pair); uint256 reserve0 = values[0]; uint256 reserve1 = values[1]; if (pair.token0() == stablecoin) { return router.getAmountIn(multiplier, reserve0, reserve1); } return router.getAmountIn(multiplier, reserve1, reserve0); } function getNpmPriceInternal(IStore s, uint256 multiplier) external view returns (uint256) { return getPriceInternal(s, s.getNpmTokenAddress(), s.getStablecoin(), multiplier); } function _getReserve0Key(IUniswapV2PairLike pair) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LP_RESERVE0, pair)); } function _getReserve1Key(IUniswapV2PairLike pair) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LP_RESERVE1, pair)); } function _getPairTotalSupplyKey(IUniswapV2PairLike pair) private pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LP_TOTAL_SUPPLY, pair)); } function _getPair( IStore s, address token, address stablecoin ) private view returns (IUniswapV2PairLike) { IUniswapV2FactoryLike factory = IUniswapV2FactoryLike(s.getUniswapV2Factory()); IUniswapV2PairLike pair = IUniswapV2PairLike(factory.getPair(token, stablecoin)); return pair; } }
// 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[] memory 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 /* 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 "./ProtoUtilV1.sol"; import "./CoverUtilV1.sol"; import "./RegistryLibV1.sol"; import "./StrategyLibV1.sol"; import "./ValidationLibV1.sol"; // @todo: before launch, refactor this to be invoked manually // A misconfiguration or issue on an external protocol may take the whole system down library RoutineInvokerLibV1 { using PriceLibV1 for IStore; using ProtoUtilV1 for IStore; using RegistryLibV1 for IStore; using StrategyLibV1 for IStore; using CoverUtilV1 for IStore; using StoreKeyUtil for IStore; using ValidationLibV1 for IStore; enum Action { Deposit, Withdraw } function updateStateAndLiquidity(IStore s, bytes32 key) external { _invoke(s, key, address(0)); } function _invoke( IStore s, bytes32 key, address token ) private { _updateKnownTokenPrices(s, token); if (key > 0) { _invokeAssetManagement(s, key); } } function getWithdrawalInfoInternal(IStore s, bytes32 coverKey) public view returns ( bool isWithdrawalPeriod, uint256 lendingPeriod, uint256 withdrawalWindow, uint256 start, uint256 end ) { (lendingPeriod, withdrawalWindow) = s.getLendingPeriodsInternal(coverKey); // Get the withdrawal period of this cover liquidity start = s.getUintByKey(getNextWithdrawalStartKey(coverKey)); end = s.getUintByKey(getNextWithdrawalEndKey(coverKey)); // solhint-disable-next-line if (block.timestamp >= start && block.timestamp <= end) { isWithdrawalPeriod = true; } } function _executeIsWithdrawalPeriod(IStore s, bytes32 coverKey) private returns (bool) { (bool isWithdrawalPeriod, uint256 lendingPeriod, uint256 withdrawalWindow, uint256 start, uint256 end) = getWithdrawalInfoInternal(s, coverKey); // Without a lending period and withdrawal window, deposit is not possible if (lendingPeriod == 0 || withdrawalWindow == 0) { return true; } if (isWithdrawalPeriod) { return true; } // 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(getNextWithdrawalStartKey(coverKey), start); s.setUintByKey(getNextWithdrawalEndKey(coverKey), end); setAccrualCompleteInternal(s, coverKey, false); } return false; } function isAccrualCompleteInternal(IStore s, bytes32 coverKey) external view returns (bool) { return s.getBoolByKey(getAccrualInvocationKey(coverKey)); } function setAccrualCompleteInternal( IStore s, bytes32 coverKey, bool flag ) public { s.setBoolByKey(getAccrualInvocationKey(coverKey), flag); } function getAccrualInvocationKey(bytes32 coverKey) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_ACCRUAL_INVOCATION, coverKey)); } function getNextWithdrawalStartKey(bytes32 coverKey) public pure returns (bytes32) { return keccak256(abi.encodePacked(ProtoUtilV1.NS_LENDING_STRATEGY_WITHDRAWAL_START, coverKey)); } function getNextWithdrawalEndKey(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(getNextWithdrawalStartKey(coverKey)); uint256 end = s.getUintByKey(getNextWithdrawalEndKey(coverKey)); require(block.timestamp >= start, "Withdrawal period has not started"); require(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 CoverUtilV1.CoverStatus status = s.getCoverStatus(coverKey); if (status != CoverUtilV1.CoverStatus.Normal) { // Reset the withdrawal window s.setUintByKey(getNextWithdrawalStartKey(coverKey), 0); s.setUintByKey(getNextWithdrawalEndKey(coverKey), 0); return Action.Withdraw; } if (_executeIsWithdrawalPeriod(s, coverKey) == true) { return Action.Withdraw; } return Action.Deposit; } function _canDeposit( IStore s, ILendingStrategy strategy, uint256 totalStrategies, bytes32 key ) private view returns (uint256) { address vault = s.getVaultAddress(key); IERC20 stablecoin = IERC20(s.getStablecoin()); uint256 maximumAllowed = (stablecoin.balanceOf(vault) * ProtoUtilV1.MAX_LENDING_RATIO) / ProtoUtilV1.MULTIPLIER; uint256 allocation = maximumAllowed / totalStrategies; uint256 weight = strategy.getWeight(); uint256 canDeposit = (allocation * weight) / ProtoUtilV1.MULTIPLIER; uint256 alreadyDeposited = s.getAmountInStrategy(key, strategy.getName(), address(stablecoin)); if (alreadyDeposited >= canDeposit) { return 0; } return canDeposit - alreadyDeposited; } function _invokeAssetManagement(IStore s, bytes32 key) private { address vault = s.getVaultAddress(key); _withdrawFromDisabled(s, key, 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, key); } } function _executeStrategy( IStore s, ILendingStrategy strategy, uint256 totalStrategies, address vault, bytes32 key ) private { uint256 canDeposit = _canDeposit(s, strategy, totalStrategies, key); uint256 balance = IERC20(s.getStablecoin()).balanceOf(vault); if (canDeposit > balance) { canDeposit = balance; } Action action = _executeAndGetAction(s, strategy, key); if (action == Action.Deposit && canDeposit == 0) { return; } if (action == Action.Withdraw) { _withdrawAllFromStrategy(strategy, vault, key); } else { _depositToStrategy(strategy, key, canDeposit); } } function _depositToStrategy( ILendingStrategy strategy, bytes32 key, uint256 amount ) private { strategy.deposit(key, amount); } function _withdrawAllFromStrategy( ILendingStrategy strategy, address vault, bytes32 key ) private returns (uint256 stablecoinWithdrawn) { uint256 balance = IERC20(strategy.getDepositCertificate()).balanceOf(vault); if (balance > 0) { stablecoinWithdrawn = strategy.withdraw(key); } } function _withdrawFromDisabled( IStore s, bytes32 key, 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(key); } } } function _updateKnownTokenPrices(IStore s, address token) private { address npm = s.getNpmTokenAddress(); if (token != address(0) && token != npm) { PriceLibV1.setTokenPriceInStablecoinInternal(s, token); } PriceLibV1.setTokenPriceInStablecoinInternal(s, npm); } }
// 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 "./ValidationLibV1.sol"; import "./AccessControlLibV1.sol"; import "../interfaces/IProtocol.sol"; import "../interfaces/IPausable.sol"; library BaseLibV1 { using ValidationLibV1 for IStore; /** * @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 arbitrary-send payable(sendTo).transfer(address(this).balance); } /** * @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. * @param token IERC-20 The address of the token contract */ function recoverTokenInternal(address token, address sendTo) external { // @suppress-address-trust-issue, @suppress-malicious-erc20 Although the token can't be trusted, the recovery agent has to check the token code manually. IERC20 erc20 = IERC20(token); uint256 balance = erc20.balanceOf(address(this)); if (balance > 0) { require(erc20.transfer(sendTo, balance), "Transfer failed"); } } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/libraries/AccessControlLibV1.sol": { "AccessControlLibV1": "0x98e153baa1ba322a30495d6576ffabddc74fbb8e" }, "contracts/libraries/BaseLibV1.sol": { "BaseLibV1": "0x5abccde057adf45ff7b37e9d502cec89d1c448a8" }, "contracts/libraries/cxTokenFactoryLibV1.sol": { "cxTokenFactoryLibV1": "0xa983d1b898097a6344519d44177d2b32a7f430da" }, "contracts/libraries/StoreKeyUtil.sol": { "StoreKeyUtil": "0xc8e2b8c1ac5399d8ae54b026159d0b409162e4e4" }, "contracts/libraries/ValidationLibV1.sol": { "ValidationLibV1": "0xc9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a" } } }
[{"inputs":[{"internalType":"contract IStore","name":"store","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":false,"internalType":"address","name":"cxToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"expiryDate","type":"uint256"}],"name":"CxTokenDeployed","type":"event"},{"inputs":[{"internalType":"contract IStore","name":"s","type":"address"},{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"expiryDate","type":"uint256"}],"name":"deploy","outputs":[{"internalType":"address","name":"deployed","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
608060405234801561001057600080fd5b5060405161108038038061108083398101604081905261002f9161008a565b6001600055806001600160a01b0381166100645760405162461bcd60e51b815260040161005b906100b8565b60405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055506100df565b60006020828403121561009b578081fd5b81516001600160a01b03811681146100b1578182fd5b9392505050565b6020808252600d908201526c496e76616c69642053746f726560981b604082015260600190565b610f92806100ee6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806386b714e21161005057806386b714e2146100b2578063e3242aed146100c7578063feaea586146100da57610072565b806317d7de7c1461007757806352d5999f1461009557806354fd4d50146100aa575b600080fd5b61007f6100ed565b60405161008c9190610d99565b60405180910390f35b6100a86100a3366004610b97565b610111565b005b61007f610314565b6100ba610338565b60405161008c9190610d2b565b6100ba6100d5366004610cf7565b610354565b6100a86100e8366004610bd6565b61099a565b7f6378546f6b656e466163746f727900000000000000000000000000000000000090565b60026000541415610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014e90610ed1565b60405180910390fd5b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273c9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a9163f5bd1af2916101c49173ffffffffffffffffffffffffffffffffffffffff1690600401610d2b565b60006040518083038186803b1580156101dc57600080fd5b505af41580156101f0573d6000803e3d6000fd5b50506001546040517ff268c9e00000000000000000000000000000000000000000000000000000000081527398e153baa1ba322a30495d6576ffabddc74fbb8e935063f268c9e0925061025c9173ffffffffffffffffffffffffffffffffffffffff1690600401610d2b565b60006040518083038186803b15801561027457600080fd5b505af4158015610288573d6000803e3d6000fd5b50506040517f9075c922000000000000000000000000000000000000000000000000000000008152735abccde057adf45ff7b37e9d502cec89d1c448a89250639075c92291506102dc908490600401610d2b565b60006040518083038186803b1580156102f457600080fd5b505af4158015610308573d6000803e3d6000fd5b50506001600055505050565b7f76302e310000000000000000000000000000000000000000000000000000000090565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b600060026000541415610393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014e90610ed1565b60026000556040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273c9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a9063f5bd1af2906103fe9073ffffffffffffffffffffffffffffffffffffffff881690600401610d2b565b60006040518083038186803b15801561041657600080fd5b505af415801561042a573d6000803e3d6000fd5b50506040517ff929aba300000000000000000000000000000000000000000000000000000000815273c9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a925063f929aba391506104969073ffffffffffffffffffffffffffffffffffffffff8816908790600401610d73565b60006040518083038186803b1580156104ae57600080fd5b505af41580156104c2573d6000803e3d6000fd5b50506040517f5a741ad700000000000000000000000000000000000000000000000000000000815273c9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a9250635a741ad7915061052c9073ffffffffffffffffffffffffffffffffffffffff881690600401610d2b565b60006040518083038186803b15801561054457600080fd5b505af4158015610558573d6000803e3d6000fd5b5050505060008211610596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014e90610e63565b60008073a983d1b898097a6344519d44177d2b32a7f430da63bcb63d508787876040518463ffffffff1660e01b81526004016105d493929190610e35565b60006040518083038186803b1580156105ec57600080fd5b505af4158015610600573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106469190810190610c0e565b6040517f21f8a721000000000000000000000000000000000000000000000000000000008152919350915060009073ffffffffffffffffffffffffffffffffffffffff8816906321f8a721906106a0908590600401610d99565b60206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f09190610bba565b73ffffffffffffffffffffffffffffffffffffffff161461073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014e90610e9a565b8082516020840134f59250823b61075357600080fd5b6040517fca446dd900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169063ca446dd9906107a79084908790600401610da2565b600060405180830381600087803b1580156107c157600080fd5b505af11580156107d5573d6000803e3d6000fd5b50506040517fb25c8f7600000000000000000000000000000000000000000000000000000000815273c8e2b8c1ac5399d8ae54b026159d0b409162e4e4925063b25c8f7691506108669073ffffffffffffffffffffffffffffffffffffffff8a16907f6e733a636f7665723a6378746f6b656e00000000000000000000000000000000908890600190600401610dc6565b60006040518083038186803b15801561087e57600080fd5b505af4158015610892573d6000803e3d6000fd5b50506040517fab23c03600000000000000000000000000000000000000000000000000000000815273c8e2b8c1ac5399d8ae54b026159d0b409162e4e4925063ab23c03691506109229073ffffffffffffffffffffffffffffffffffffffff8a16907f6e733a636f7665723a6378746f6b656e00000000000000000000000000000000908a908990600401610dfd565b60006040518083038186803b15801561093a57600080fd5b505af415801561094e573d6000803e3d6000fd5b50505050847f1aa74c86504f0e6f2f1243be95ace0c06600121484f11346163175e50b9348108486604051610984929190610d73565b60405180910390a2505060016000559392505050565b600260005414156109d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014e90610ed1565b60026000556001546040517ff5bd1af200000000000000000000000000000000000000000000000000000000815273c9cf93da8a1dc0b05dbe2c20083fc89dbbdd3d2a9163f5bd1af291610a449173ffffffffffffffffffffffffffffffffffffffff1690600401610d2b565b60006040518083038186803b158015610a5c57600080fd5b505af4158015610a70573d6000803e3d6000fd5b50506001546040517ff268c9e00000000000000000000000000000000000000000000000000000000081527398e153baa1ba322a30495d6576ffabddc74fbb8e935063f268c9e09250610adc9173ffffffffffffffffffffffffffffffffffffffff1690600401610d2b565b60006040518083038186803b158015610af457600080fd5b505af4158015610b08573d6000803e3d6000fd5b50506040517f707bf3d4000000000000000000000000000000000000000000000000000000008152735abccde057adf45ff7b37e9d502cec89d1c448a8925063707bf3d49150610b5e9085908590600401610d4c565b60006040518083038186803b158015610b7657600080fd5b505af4158015610b8a573d6000803e3d6000fd5b5050600160005550505050565b600060208284031215610ba8578081fd5b8135610bb381610f37565b9392505050565b600060208284031215610bcb578081fd5b8151610bb381610f37565b60008060408385031215610be8578081fd5b8235610bf381610f37565b91506020830135610c0381610f37565b809150509250929050565b60008060408385031215610c20578182fd5b825167ffffffffffffffff80821115610c37578384fd5b818501915085601f830112610c4a578384fd5b815181811115610c5c57610c5c610f08565b6040516020807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501168301018281108582111715610c9f57610c9f610f08565b6040528282528483018101891015610cb5578687fd5b8693505b82841015610cd65784840181015182850182015292830192610cb9565b82841115610ce657868184840101525b969096015195979596505050505050565b600080600060608486031215610d0b578081fd5b8335610d1681610f37565b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b90815260200190565b91825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9485168152602081019390935292166040820152901515606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff948516815260208101939093526040830191909152909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff9390931683526020830191909152604082015260600190565b6020808252601a908201527f506c656173652073706563696679206578706972792064617465000000000000604082015260600190565b60208082526010908201527f416c7265616479206465706c6f79656400000000000000000000000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610f5957600080fd5b5056fea26469706673582212206b7d1575efe6980bebdce50e11ff04e1bfb2f92310c306db8a80f302d2ed1b5d64736f6c63430008000033000000000000000000000000022b098e17be5aaea3fa70abcf7501519aaedc04
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000022b098e17be5aaea3fa70abcf7501519aaedc04
-----Decoded View---------------
Arg [0] : store (address): 0x022b098e17be5aaea3fa70abcf7501519aaedc04
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000022b098e17be5aaea3fa70abcf7501519aaedc04
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|