├── .env.sample
├── .github
├── CONTRIBUTING
└── workflows
│ └── test.yml
├── .gitignore
├── .gitmodules
├── .prettierrc
├── .solcover.js
├── .solhint.json
├── .solhintignore
├── .vscode
└── settings.json
├── LICENSE
├── abis
├── IAaveV2LendingPoolLike.json
├── IBondPool.json
├── IClaimsProcessor.json
├── ICompoundERC20DelegatorLike.json
├── ICover.json
├── ICoverReassurance.json
├── ICoverStake.json
├── ICxToken.json
├── ICxTokenFactory.json
├── IERC20.json
├── IERC20Detailed.json
├── IFinalization.json
├── IGovernance.json
├── ILendingStrategy.json
├── ILiquidityEngine.json
├── IMember.json
├── IPausable.json
├── IPolicy.json
├── IPolicyAdmin.json
├── IPriceOracle.json
├── IProtocol.json
├── IRecoverable.json
├── IReporter.json
├── IResolution.json
├── IResolvable.json
├── IStakingPools.json
├── IStore.json
├── IUniswapV2FactoryLike.json
├── IUniswapV2PairLike.json
├── IUniswapV2RouterLike.json
├── IUnstakable.json
├── IVault.json
├── IVaultDelegate.json
├── IVaultFactory.json
└── IWitness.json
├── audits
├── 001-blocksec.pdf
└── 002-open-zeppelin.pdf
├── contracts
├── core
│ ├── ProtoBase.sol
│ ├── Protocol.sol
│ ├── Recoverable.sol
│ ├── claims
│ │ └── Processor.sol
│ ├── cxToken
│ │ ├── cxToken.sol
│ │ └── cxTokenFactory.sol
│ ├── delegates
│ │ ├── VaultDelegate.sol
│ │ ├── VaultDelegateBase.sol
│ │ └── VaultDelegateWithFlashLoan.sol
│ ├── governance
│ │ ├── Governance.sol
│ │ ├── Reporter.sol
│ │ ├── Witness.sol
│ │ └── resolution
│ │ │ ├── Finalization.sol
│ │ │ ├── Resolution.sol
│ │ │ ├── Resolvable.sol
│ │ │ └── Unstakable.sol
│ ├── lifecycle
│ │ ├── Cover.sol
│ │ ├── CoverBase.sol
│ │ ├── CoverReassurance.sol
│ │ └── CoverStake.sol
│ ├── liquidity
│ │ ├── LiquidityEngine.sol
│ │ ├── Vault.sol
│ │ ├── VaultBase.sol
│ │ ├── VaultFactory.sol
│ │ ├── VaultLiquidity.sol
│ │ ├── VaultStrategy.sol
│ │ ├── WithFlashLoan.sol
│ │ └── strategies
│ │ │ ├── AaveStrategy.sol
│ │ │ └── CompoundStrategy.sol
│ ├── policy
│ │ ├── Policy.sol
│ │ └── PolicyAdmin.sol
│ ├── store
│ │ ├── Store.sol
│ │ └── StoreBase.sol
│ └── token
│ │ ├── Delayable.sol
│ │ ├── NPM.sol
│ │ ├── POT.sol
│ │ ├── Treasury.sol
│ │ ├── WithPausability.sol
│ │ └── WithRecovery.sol
├── dependencies
│ ├── BokkyPooBahsDateTimeLibrary.sol
│ ├── aave
│ │ └── IAaveV2LendingPoolLike.sol
│ ├── compound
│ │ └── ICompoundERC20DelegatorLike.sol
│ └── uniswap-v2
│ │ ├── IUniswapV2FactoryLike.sol
│ │ ├── IUniswapV2PairLike.sol
│ │ └── IUniswapV2RouterLike.sol
├── examples
│ └── NpmDistributor.sol
├── fakes
│ ├── Destroyable.sol
│ ├── FakeAaveLendingPool.sol
│ ├── FakeCompoundStablecoinDelegator.sol
│ ├── FakePriceOracle.sol
│ ├── FakeRecoverable.sol
│ ├── FakeStore.sol
│ ├── FakeToken.sol
│ ├── FakeUniswapPair.sol
│ ├── FakeUniswapV2FactoryLike.sol
│ ├── FakeUniswapV2PairLike.sol
│ ├── FakeUniswapV2RouterLike.sol
│ ├── FaultyAaveLendingPool.sol
│ ├── FaultyCompoundStablecoinDelegator.sol
│ ├── ForceEther.sol
│ ├── InvalidStrategy.sol
│ ├── MaliciousToken.sol
│ ├── NTransferUtilV2Intermediate.sol
│ └── PoorMansERC20.sol
├── interfaces
│ ├── IBondPool.sol
│ ├── IClaimsProcessor.sol
│ ├── ICover.sol
│ ├── ICoverReassurance.sol
│ ├── ICoverStake.sol
│ ├── ICxToken.sol
│ ├── ICxTokenFactory.sol
│ ├── IERC20Detailed.sol
│ ├── IFinalization.sol
│ ├── IGovernance.sol
│ ├── ILendingStrategy.sol
│ ├── ILiquidityEngine.sol
│ ├── IMember.sol
│ ├── IPausable.sol
│ ├── IPolicy.sol
│ ├── IPolicyAdmin.sol
│ ├── IPriceOracle.sol
│ ├── IProtocol.sol
│ ├── IRecoverable.sol
│ ├── IReporter.sol
│ ├── IResolution.sol
│ ├── IResolvable.sol
│ ├── IStakingPools.sol
│ ├── IStore.sol
│ ├── IUnstakable.sol
│ ├── IVault.sol
│ ├── IVaultDelegate.sol
│ ├── IVaultFactory.sol
│ └── IWitness.sol
├── libraries
│ ├── AccessControlLibV1.sol
│ ├── BaseLibV1.sol
│ ├── BondPoolLibV1.sol
│ ├── CoverLibV1.sol
│ ├── CoverUtilV1.sol
│ ├── GovernanceUtilV1.sol
│ ├── NTransferUtilV2.sol
│ ├── PolicyHelperV1.sol
│ ├── PriceLibV1.sol
│ ├── ProtoUtilV1.sol
│ ├── RegistryLibV1.sol
│ ├── RoutineInvokerLibV1.sol
│ ├── StakingPoolCoreLibV1.sol
│ ├── StakingPoolLibV1.sol
│ ├── StoreKeyUtil.sol
│ ├── StrategyLibV1.sol
│ ├── ValidationLibV1.sol
│ ├── VaultFactoryLibV1.sol
│ ├── VaultLibV1.sol
│ └── cxTokenFactoryLibV1.sol
├── mock
│ ├── MockFlashBorrower.sol
│ ├── MockRegistryClient.sol
│ ├── base
│ │ ├── MockCxToken.sol
│ │ ├── MockProtocol.sol
│ │ └── MockStore.sol
│ ├── claims-processor
│ │ ├── MockProcessorStore.sol
│ │ └── MockVault.sol
│ ├── cx-token
│ │ ├── MockCxTokenPolicy.sol
│ │ └── MockCxTokenStore.sol
│ └── lib-user
│ │ ├── MockAccessControlUser.sol
│ │ ├── MockCoverUtil.sol
│ │ ├── MockLiquidityEngineUser.sol
│ │ ├── MockStoreKeyUtilUser.sol
│ │ ├── MockValidationLibUser.sol
│ │ └── MockVaultLibUser.sol
└── pool
│ ├── Bond
│ ├── BondPool.sol
│ └── BondPoolBase.sol
│ └── Staking
│ ├── StakingPoolBase.sol
│ ├── StakingPoolInfo.sol
│ ├── StakingPoolReward.sol
│ └── StakingPools.sol
├── docs
├── AaveStrategy.md
├── AccessControl.md
├── AccessControlLibV1.md
├── Address.md
├── BaseLibV1.md
├── BokkyPooBahsDateTimeLibrary.md
├── BondPool.md
├── BondPoolBase.md
├── BondPoolLibV1.md
├── CompoundStrategy.md
├── Context.md
├── Cover.md
├── CoverBase.md
├── CoverLibV1.md
├── CoverReassurance.md
├── CoverStake.md
├── CoverUtilV1.md
├── Delayable.md
├── Destroyable.md
├── ERC165.md
├── ERC20.md
├── FakeAaveLendingPool.md
├── FakeCompoundStablecoinDelegator.md
├── FakePriceOracle.md
├── FakeRecoverable.md
├── FakeStore.md
├── FakeToken.md
├── FakeUniswapPair.md
├── FakeUniswapV2FactoryLike.md
├── FakeUniswapV2PairLike.md
├── FakeUniswapV2RouterLike.md
├── FaultyAaveLendingPool.md
├── FaultyCompoundStablecoinDelegator.md
├── Finalization.md
├── ForceEther.md
├── Governance.md
├── GovernanceUtilV1.md
├── IAaveV2LendingPoolLike.md
├── IAccessControl.md
├── IBondPool.md
├── IClaimsProcessor.md
├── ICompoundERC20DelegatorLike.md
├── ICover.md
├── ICoverReassurance.md
├── ICoverStake.md
├── ICxToken.md
├── ICxTokenFactory.md
├── IERC165.md
├── IERC20.md
├── IERC20Detailed.md
├── IERC20Metadata.md
├── IERC3156FlashBorrower.md
├── IERC3156FlashLender.md
├── IFinalization.md
├── IGovernance.md
├── ILendingStrategy.md
├── ILiquidityEngine.md
├── IMember.md
├── INeptuneRouterV1.md
├── IPausable.md
├── IPolicy.md
├── IPolicyAdmin.md
├── IPriceOracle.md
├── IProtocol.md
├── IRecoverable.md
├── IReporter.md
├── IResolution.md
├── IResolvable.md
├── IStakingPools.md
├── IStore.md
├── IStoreLike.md
├── IUniswapV2FactoryLike.md
├── IUniswapV2PairLike.md
├── IUniswapV2RouterLike.md
├── IUnstakable.md
├── IVault.md
├── IVaultDelegate.md
├── IVaultFactory.md
├── IWitness.md
├── InvalidStrategy.md
├── LiquidityEngine.md
├── MaliciousToken.md
├── MockAccessControlUser.md
├── MockCoverUtilUser.md
├── MockCxToken.md
├── MockCxTokenPolicy.md
├── MockCxTokenStore.md
├── MockFlashBorrower.md
├── MockLiquidityEngineUser.md
├── MockProcessorStore.md
├── MockProcessorStoreLib.md
├── MockProtocol.md
├── MockRegistryClient.md
├── MockStore.md
├── MockStoreKeyUtilUser.md
├── MockValidationLibUser.md
├── MockVault.md
├── MockVaultLibUser.md
├── NPM.md
├── NTransferUtilV2.md
├── NTransferUtilV2Intermediate.md
├── NeptuneRouterV1.md
├── NpmDistributor.md
├── Ownable.md
├── POT.md
├── Pausable.md
├── Policy.md
├── PolicyAdmin.md
├── PolicyHelperV1.md
├── PoorMansERC20.md
├── PriceLibV1.md
├── Processor.md
├── ProtoBase.md
├── ProtoUtilV1.md
├── Protocol.md
├── Recoverable.md
├── ReentrancyGuard.md
├── RegistryLibV1.md
├── Reporter.md
├── Resolution.md
├── Resolvable.md
├── RoutineInvokerLibV1.md
├── SafeERC20.md
├── StakingPoolBase.md
├── StakingPoolCoreLibV1.md
├── StakingPoolInfo.md
├── StakingPoolLibV1.md
├── StakingPoolReward.md
├── StakingPools.md
├── Store.md
├── StoreBase.md
├── StoreKeyUtil.md
├── StrategyLibV1.md
├── Strings.md
├── TimelockController.md
├── Unstakable.md
├── ValidationLibV1.md
├── Vault.md
├── VaultBase.md
├── VaultDelegate.md
├── VaultDelegateBase.md
├── VaultDelegateWithFlashLoan.md
├── VaultFactory.md
├── VaultFactoryLibV1.md
├── VaultLibV1.md
├── VaultLiquidity.md
├── VaultStrategy.md
├── WithFlashLoan.md
├── WithPausability.md
├── WithRecovery.md
├── Witness.md
├── cxToken.md
├── cxTokenFactory.md
└── cxTokenFactoryLibV1.md
├── events.md
├── examples
├── dedicated
│ ├── exchanges
│ │ ├── binance.js
│ │ ├── coinbase.js
│ │ ├── huobi.js
│ │ ├── index.js
│ │ └── okx.js
│ └── index.js
├── diversified
│ ├── animoca
│ │ ├── cover.js
│ │ └── products
│ │ │ └── index.js
│ ├── defi
│ │ ├── cover.js
│ │ ├── index.js
│ │ └── products
│ │ │ ├── 1inch.js
│ │ │ ├── compound.js
│ │ │ ├── convex.js
│ │ │ ├── index.js
│ │ │ ├── kyberswap.js
│ │ │ ├── lido.js
│ │ │ ├── loopring.js
│ │ │ ├── nexus-mutual.js
│ │ │ ├── rocket-pool.js
│ │ │ ├── sushi.js
│ │ │ └── uniswap.js
│ ├── index.js
│ └── prime
│ │ ├── cover.js
│ │ ├── index.js
│ │ └── products
│ │ ├── aave.js
│ │ ├── balancer.js
│ │ ├── curve.js
│ │ ├── gnosis-safe.js
│ │ ├── index.js
│ │ ├── maker.js
│ │ ├── synthetix.js
│ │ └── uniswap.js
└── index.js
├── files
└── protocol.png
├── foundry.toml
├── fuzzing
├── CoverSpec.sol
└── core
│ ├── StoreTest.sol
│ └── VaultTest.sol
├── hardhat.config.js
├── oracle
├── contracts
│ ├── IPriceOracle.sol
│ └── NpmPriceOracle.sol
├── hardhat.config.js
├── package.json
├── scripts
│ └── deploy.js
└── yarn.lock
├── package.json
├── readme.md
├── remappings.txt
├── scripts
├── config
│ ├── deployments
│ │ ├── arbitrum.json
│ │ ├── basegoerli.json
│ │ ├── bsc.json
│ │ └── ethereum.json
│ ├── index.js
│ └── network
│ │ ├── arbitrum.js
│ │ ├── base-goerli.js
│ │ ├── bsc.js
│ │ ├── hardhat.js
│ │ ├── index.js
│ │ ├── local.js
│ │ └── mainnet.js
├── covers
│ ├── dedicated
│ │ ├── binance.js
│ │ └── okx.js
│ ├── deployments
│ │ ├── binance.js
│ │ ├── okx.js
│ │ ├── popular-defi-apps-bnb.js
│ │ ├── popular-defi-apps.js
│ │ └── prime-dapps.js
│ └── diversified
│ │ ├── popular-defi-apps-bnb
│ │ ├── cover.js
│ │ ├── index.js
│ │ └── products
│ │ │ ├── alpaca.js
│ │ │ ├── dodo.js
│ │ │ ├── index.js
│ │ │ ├── one-inch.js
│ │ │ ├── pancakeswap.js
│ │ │ └── uniswap.js
│ │ ├── popular-defi-apps
│ │ ├── cover.js
│ │ ├── index.js
│ │ └── products
│ │ │ ├── aave.js
│ │ │ ├── bancor.js
│ │ │ ├── compound.js
│ │ │ ├── convex.js
│ │ │ ├── dydx.js
│ │ │ ├── gmx.js
│ │ │ ├── index.js
│ │ │ ├── one-inch.js
│ │ │ ├── sushi.js
│ │ │ └── uniswap.js
│ │ └── prime
│ │ ├── cover.js
│ │ ├── index.js
│ │ └── products
│ │ ├── aave.js
│ │ ├── balancer.js
│ │ ├── curve.js
│ │ ├── gnosis-safe.js
│ │ ├── index.js
│ │ ├── maker.js
│ │ ├── synthetix.js
│ │ └── uniswap.js
├── deploy-covers.js
├── deploy-npm.js
├── deploy-pot.js
├── deploy-treasury.js
├── deploy.js
├── update-oracle.js
├── upgrade
│ ├── bond-pool.js
│ ├── resolution.js
│ └── vault-delegate.js
└── verify.js
├── security.md
├── slither.config.json
├── solidoc.json
├── sonar-project.properties
├── test
├── bdd
│ └── fractionalization.js
├── examples
│ └── distributor
│ │ ├── add-liquidity.spec.js
│ │ ├── ctor.spec.js
│ │ ├── deps.js
│ │ ├── drain.spec.js
│ │ ├── get-premium.spec.js
│ │ ├── purchase-policy.spec.js
│ │ └── remove-liquidity.spec.js
├── specs
│ ├── claims-processor
│ │ ├── claim.spec.js
│ │ ├── ctor-vfns.spec.js
│ │ ├── deps.js
│ │ ├── set-claim-period.spec.js
│ │ └── validate.spec.js
│ ├── cx-token-factory
│ │ ├── ctor.spec.js
│ │ ├── deploy.spec.js
│ │ └── deps.js
│ ├── cx-token
│ │ ├── before-token-transfer.spec.js
│ │ ├── burn.spec.js
│ │ ├── ctor-vfns.spec.js
│ │ ├── deps.js
│ │ ├── get-claimable-policy-of.spec.js
│ │ ├── get-coverage-starts-from.spec.js
│ │ └── mint.spec.js
│ ├── governance
│ │ ├── attest.spec.js
│ │ ├── close-report.spec.js
│ │ ├── ctor.spec.js
│ │ ├── deps.js
│ │ ├── dispute.spec.js
│ │ ├── emergency-resolve.spec.js
│ │ ├── finalize.spec.js
│ │ ├── get-resolution-date.spec.js
│ │ ├── refute.spec.js
│ │ ├── report.spec.js
│ │ ├── resolution
│ │ │ ├── configure-cool-down-period.spec.js
│ │ │ ├── ctor.spec.js
│ │ │ ├── deps.js
│ │ │ ├── get-cool-down-period.spec.js
│ │ │ ├── get-resolution-deadline.spec.js
│ │ │ ├── get-unstake-info-for.spec.js
│ │ │ ├── unstake-with-claim.spec.js
│ │ │ └── unstake.spec.js
│ │ ├── resolve.spec.js
│ │ ├── set-first-reporting-stake.spec.js
│ │ ├── set-reporter-burn-rate.spec.js
│ │ └── set-reporter-commission.spec.js
│ ├── libraries
│ │ ├── access-control.spec.js
│ │ ├── cover-util.spec.js
│ │ ├── deps.js
│ │ ├── routine-invoker.spec.js
│ │ ├── store-key-util.spec.js
│ │ ├── validation.spec.js
│ │ └── vault.spec.js
│ ├── lifecycle
│ │ ├── cover-reassurance
│ │ │ ├── add-reassurance.spec.js
│ │ │ ├── capitalize-pool.spec.js
│ │ │ ├── ctor-vfns.spec.js
│ │ │ ├── deps.js
│ │ │ ├── get-reassurance.spec.js
│ │ │ └── set-weight.spec.js
│ │ ├── cover-stake
│ │ │ ├── ctor-vfns.spec.js
│ │ │ ├── decrease-stake.spec.js
│ │ │ ├── deps.js
│ │ │ ├── increase-stake.spec.js
│ │ │ └── stake-of.spec.js
│ │ └── cover
│ │ │ ├── add-cover.spec.js
│ │ │ ├── add-product.spec.js
│ │ │ ├── ctor-vfns.spec.js
│ │ │ ├── deps.js
│ │ │ ├── disable-policy.spec.js
│ │ │ ├── initialize.spec.js
│ │ │ ├── set-cover-creation-fee.spec.js
│ │ │ ├── set-min-cover-creation-stake.spec.js
│ │ │ ├── set-min-stake-to-add-liquidity.spec.js
│ │ │ ├── update-cover-creator-whitelist.spec.js
│ │ │ ├── update-cover-users-whitelist.spec.js
│ │ │ ├── update-cover.spec.js
│ │ │ └── update-product.spec.js
│ ├── liquidity
│ │ ├── delegates
│ │ │ ├── ctor-vfns.spec.js
│ │ │ └── deps.js
│ │ ├── engine
│ │ │ ├── add-strategies.spec.js
│ │ │ ├── ctor.spec.js
│ │ │ ├── delete-strategy.spec.js
│ │ │ ├── deps.js
│ │ │ ├── disable-strategy.spec.js
│ │ │ ├── set-liquidity-state-update-interval.spec.js
│ │ │ ├── set-max-lending-ratio.spec.js
│ │ │ └── set-risk-pooling-periods.spec.js
│ │ ├── strategy
│ │ │ ├── aave
│ │ │ │ ├── ctor.spec.js
│ │ │ │ ├── deposit.spec.js
│ │ │ │ ├── drain.spec.js
│ │ │ │ └── withdraw.spec.js
│ │ │ ├── compound
│ │ │ │ ├── ctor.spec.js
│ │ │ │ ├── deposit.spec.js
│ │ │ │ ├── drain.spec.js
│ │ │ │ └── withdraw.spec.js
│ │ │ └── deps.js
│ │ ├── vault-factory
│ │ │ ├── ctor.spec.js
│ │ │ └── deps.js
│ │ └── vault
│ │ │ ├── add-liquidity.spec.js
│ │ │ ├── calculate-liquidity.spec.js
│ │ │ ├── calculate-pods.spec.js
│ │ │ ├── ctor.spec.js
│ │ │ ├── deps.js
│ │ │ ├── flash-fee.spec.js
│ │ │ ├── flashloan.spec.js
│ │ │ ├── get-info.spec.js
│ │ │ ├── max-flash-loan.spec.js
│ │ │ ├── receive-from-strategy.spec.js
│ │ │ ├── remove-liquidity.spec.js
│ │ │ ├── transfer-governance.spec.js
│ │ │ └── transfer-to-strategy.spec.js
│ ├── policy-admin
│ │ ├── ctor.spec.js
│ │ ├── deps.js
│ │ ├── set-coverage-lag.spec.js
│ │ └── set-policy-rates-by-key.spec.js
│ ├── policy
│ │ ├── ctor.spec.js
│ │ ├── deps.js
│ │ ├── get-cover-fee-info.spec.js
│ │ ├── get-cxtoken-by-expiry-date.spec.js
│ │ ├── purchase-cover.spec.js
│ │ └── util
│ │ │ ├── calculator.js
│ │ │ └── calculator.spec.js
│ ├── pool
│ │ ├── bond
│ │ │ ├── calculate-tokens-for-lp.spec.js
│ │ │ ├── claim-bond.spec.js
│ │ │ ├── create-bond.spec.js
│ │ │ ├── ctor.spec.js
│ │ │ ├── deps.js
│ │ │ ├── get-info.spec.js
│ │ │ ├── npm-token-price.spec.js
│ │ │ └── setup.spec.js
│ │ └── staking
│ │ │ ├── add-or-edit-pool.spec.js
│ │ │ ├── close-pool.spec.js
│ │ │ ├── ctor-vfns.spec.js
│ │ │ ├── deposit.spec.js
│ │ │ ├── deposit.target.achieved.spec.js
│ │ │ ├── deps.js
│ │ │ ├── withdraw-rewards.spec.js
│ │ │ ├── withdrawal.spec.js
│ │ │ └── zero-reward.spec.js
│ ├── protocol
│ │ ├── add-contract.spec.js
│ │ ├── add-member.spec.js
│ │ ├── ctor-vfns.spec.js
│ │ ├── deps.js
│ │ ├── grant-role.spec.js
│ │ ├── pause.spec.js
│ │ ├── remove-member.spec.js
│ │ ├── setup-role.spec.js
│ │ ├── unpause.spec.js
│ │ └── upgrade-contract.spec.js
│ ├── recoverable
│ │ ├── ctor.spec.js
│ │ ├── deps.js
│ │ ├── ethers.spec.js
│ │ └── token.spec.js
│ ├── store
│ │ ├── add-uint.spec.js
│ │ ├── count-address-array-items.spec.js
│ │ ├── delete-address-array-item-by-index.spec.js
│ │ ├── delete-address-array-item.spec.js
│ │ ├── delete-bool.spec.js
│ │ ├── delete-bytes.spec.js
│ │ ├── delete-bytes32.spec.js
│ │ ├── delete-int.spec.js
│ │ ├── delete-string.spec.js
│ │ ├── delete-uint.spec.js
│ │ ├── delete-uints.spec.js
│ │ ├── get-address-array-item-by-index.spec.js
│ │ ├── get-address-values.spec.js
│ │ ├── get-uint-values.spec.js
│ │ ├── pausable.spec.js
│ │ ├── recoverable.spec.js
│ │ ├── set-address-array-item.spec.js
│ │ ├── set-address-boolean.spec.js
│ │ ├── set-address.spec.js
│ │ ├── set-bool.spec.js
│ │ ├── set-bytes.spec.js
│ │ ├── set-bytes32-array-item.spec.js
│ │ ├── set-bytes32.spec.js
│ │ ├── set-int.spec.js
│ │ ├── set-string.spec.js
│ │ ├── set-uint.spec.js
│ │ ├── set-uints.spec.js
│ │ └── subtract-uint.spec.js
│ └── token
│ │ ├── delayable.spec.js
│ │ ├── npm.spec.js
│ │ ├── recoverable.spec.js
│ │ └── treasury.spec.js
└── stories
│ ├── 0. setup.spec.js
│ ├── 1. policy.spec.js
│ ├── 2. governance.spec.js
│ ├── 3.staking.pool.spec.js
│ ├── 4.liquidity.spec.js
│ └── 5.coverage.claim.spec.js
├── truffle-config.js
├── util
├── analyzers
│ ├── chain-state.js
│ └── validators
│ │ ├── access-control.js
│ │ ├── accidental-zero.js
│ │ ├── address.js
│ │ ├── erc-20.js
│ │ ├── fraction.js
│ │ ├── index.js
│ │ ├── initialization.js
│ │ ├── lib.js
│ │ ├── mock.js
│ │ ├── non-reentrancy.js
│ │ ├── not-implemented.js
│ │ ├── pausable.js
│ │ ├── revert.js
│ │ ├── subtraction.js
│ │ ├── todo.js
│ │ └── zero-value.js
├── attach
│ ├── attach.js
│ ├── index.js
│ └── protocol.js
├── block-time.js
├── block.js
├── composer
│ ├── add-pools.js
│ ├── covers.js
│ ├── external-protocols.js
│ ├── fakes.js
│ ├── grant-roles.js
│ ├── index.js
│ ├── initializer.js
│ ├── libs.js
│ ├── pod-staking.js
│ ├── store.js
│ ├── testnet
│ │ └── staking-pools.js
│ ├── token.js
│ ├── uniswap-pair.js
│ └── vault.js
├── contract-helper
│ ├── erc20.js
│ ├── faucet.js
│ └── uniswap.js
├── count-lines
│ └── index.js
├── cxToken.js
├── demo-data
│ ├── add-liquidity.js
│ ├── add-reassurance.js
│ ├── index.js
│ └── purchase-policy.js
├── deployer.js
├── events
│ ├── all.js
│ ├── index.js
│ └── table.js
├── extract
│ ├── abis
│ │ └── index.js
│ ├── genabi.js
│ └── keys
│ │ ├── code-generator-as.js
│ │ ├── code-generator.js
│ │ ├── index.js
│ │ ├── processor.js
│ │ ├── requirement.js
│ │ ├── template-as.js
│ │ ├── template-js.js
│ │ ├── template-ts.js
│ │ └── template.js
├── file-cache
│ ├── addresses.js
│ ├── contract.js
│ ├── data.js
│ ├── index.js
│ └── upgrade.js
├── helper.js
├── index.js
├── intermediate.js
├── io.js
├── ipfs.js
├── key.js
├── net
│ └── ipfs-client.js
├── network.js
├── sample.js
├── store-util.js
├── typedefs.js
└── wallet.js
└── yarn.lock
/.env.sample:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 | POLYGONSCAN_API_KEY=
3 | ETHERSCAN_API_KEY=
4 | ALCHEMY_API_URL=
5 | ROPSTEN_RPC_URL=
6 | KOVAN_RPC_URL=
7 | ETHEREUM_RPC_URL=
8 | ARBITRUM_RPC_URL=
9 | BSC_RPC_URL=
10 | NPM_IPFS_API_URL=
--------------------------------------------------------------------------------
/.github/CONTRIBUTING:
--------------------------------------------------------------------------------
1 | ## Installation
2 |
3 | ### Checklist
4 |
5 | - [ ] Install [foundry](https://book.getfoundry.sh/getting-started/installation)
6 | - [ ] Install [lcov](https://formulae.brew.sh/formula/lcov) on Mac OS or [genhtml](https://manpages.ubuntu.com/manpages/xenial/man1/genhtml.1.html) on Linux
7 |
8 | ```
9 | git submodule update --init --recursive
10 | forge install
11 | yarn install
12 | ```
13 |
14 | ### Commands
15 |
16 | **Build**
17 |
18 | ```
19 | yarn build
20 | ```
21 |
22 | **Test**
23 |
24 | ```
25 | yarn test
26 | ```
27 |
28 | **Coverage**
29 |
30 | ```
31 | yarn coverage
32 |
33 | open ./coverage/index.html
34 | ```
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on: workflow_dispatch
4 |
5 | env:
6 | FOUNDRY_PROFILE: ci
7 |
8 | jobs:
9 | check:
10 | strategy:
11 | fail-fast: true
12 |
13 | name: Foundry project
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 | with:
18 | submodules: recursive
19 |
20 | - name: Install Foundry
21 | uses: foundry-rs/foundry-toolchain@v1
22 | with:
23 | version: nightly
24 |
25 | - name: Run Forge build
26 | run: |
27 | forge --version
28 | forge build --sizes
29 | id: build
30 |
31 | - name: Run Forge tests
32 | run: |
33 | forge test -vvv
34 | id: test
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | node_modules
3 | yarn-error.log
4 | artifacts
5 | build
6 | _*.sol*
7 | cache*
8 | coverage
9 | coverage.json
10 | walk
11 | !.github
12 | out/
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/forge-std"]
2 | path = lib/forge-std
3 | url = https://github.com/foundry-rs/forge-std
4 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "overrides": [
3 | {
4 | "files": "*.sol",
5 | "options": {
6 | "printWidth": 200,
7 | "tabWidth": 2,
8 | "useTabs": false,
9 | "singleQuote": false,
10 | "bracketSpacing": false,
11 | "explicitTypes": "always",
12 | "format": ""
13 | }
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/.solcover.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | peephole: false,
3 | inliner: false,
4 | jumpdestRemover: false,
5 | orderLiterals: true,
6 | deduplicate: false,
7 | cse: false,
8 | constantOptimizer: false,
9 | yul: false,
10 | configureYulOptimizer: true,
11 | skipFiles: ['fakes', 'mock', 'dependencies']
12 | }
--------------------------------------------------------------------------------
/.solhint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "solhint:all",
3 | "rules": {
4 | "avoid-throw": "off",
5 | "avoid-suicide": "error",
6 | "avoid-sha3": "warn",
7 | "compiler-version": [
8 | "error",
9 | "0.8.0"
10 | ],
11 | "comprehensive-interface": "off",
12 | "max-line-length": "off",
13 | "ordering": "off",
14 | "func-visibility": [
15 | "error",
16 | {
17 | "ignoreConstructors": true
18 | }
19 | ],
20 | "reason-string": "error",
21 | "quotes": [
22 | "error",
23 | "double"
24 | ],
25 | "private-vars-leading-underscore": "error"
26 | }
27 | }
--------------------------------------------------------------------------------
/.solhintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .todo
--------------------------------------------------------------------------------
/abis/IAaveV2LendingPoolLike.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "asset",
7 | "type": "address"
8 | },
9 | {
10 | "internalType": "uint256",
11 | "name": "amount",
12 | "type": "uint256"
13 | },
14 | {
15 | "internalType": "address",
16 | "name": "onBehalfOf",
17 | "type": "address"
18 | },
19 | {
20 | "internalType": "uint16",
21 | "name": "referralCode",
22 | "type": "uint16"
23 | }
24 | ],
25 | "name": "deposit",
26 | "outputs": [],
27 | "stateMutability": "nonpayable",
28 | "type": "function"
29 | },
30 | {
31 | "inputs": [
32 | {
33 | "internalType": "address",
34 | "name": "asset",
35 | "type": "address"
36 | },
37 | {
38 | "internalType": "uint256",
39 | "name": "amount",
40 | "type": "uint256"
41 | },
42 | {
43 | "internalType": "address",
44 | "name": "to",
45 | "type": "address"
46 | }
47 | ],
48 | "name": "withdraw",
49 | "outputs": [
50 | {
51 | "internalType": "uint256",
52 | "name": "",
53 | "type": "uint256"
54 | }
55 | ],
56 | "stateMutability": "nonpayable",
57 | "type": "function"
58 | }
59 | ]
--------------------------------------------------------------------------------
/abis/ICompoundERC20DelegatorLike.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "uint256",
6 | "name": "mintAmount",
7 | "type": "uint256"
8 | }
9 | ],
10 | "name": "mint",
11 | "outputs": [
12 | {
13 | "internalType": "uint256",
14 | "name": "",
15 | "type": "uint256"
16 | }
17 | ],
18 | "stateMutability": "nonpayable",
19 | "type": "function"
20 | },
21 | {
22 | "inputs": [
23 | {
24 | "internalType": "uint256",
25 | "name": "redeemTokens",
26 | "type": "uint256"
27 | }
28 | ],
29 | "name": "redeem",
30 | "outputs": [
31 | {
32 | "internalType": "uint256",
33 | "name": "",
34 | "type": "uint256"
35 | }
36 | ],
37 | "stateMutability": "nonpayable",
38 | "type": "function"
39 | }
40 | ]
--------------------------------------------------------------------------------
/abis/IFinalization.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "bytes32",
8 | "name": "coverKey",
9 | "type": "bytes32"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "bytes32",
14 | "name": "productKey",
15 | "type": "bytes32"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "finalizer",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": true,
25 | "internalType": "uint256",
26 | "name": "incidentDate",
27 | "type": "uint256"
28 | }
29 | ],
30 | "name": "Finalized",
31 | "type": "event"
32 | },
33 | {
34 | "inputs": [
35 | {
36 | "internalType": "bytes32",
37 | "name": "coverKey",
38 | "type": "bytes32"
39 | },
40 | {
41 | "internalType": "bytes32",
42 | "name": "productKey",
43 | "type": "bytes32"
44 | },
45 | {
46 | "internalType": "uint256",
47 | "name": "incidentDate",
48 | "type": "uint256"
49 | }
50 | ],
51 | "name": "finalize",
52 | "outputs": [],
53 | "stateMutability": "nonpayable",
54 | "type": "function"
55 | }
56 | ]
--------------------------------------------------------------------------------
/abis/IMember.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "name": "getName",
5 | "outputs": [
6 | {
7 | "internalType": "bytes32",
8 | "name": "",
9 | "type": "bytes32"
10 | }
11 | ],
12 | "stateMutability": "pure",
13 | "type": "function"
14 | },
15 | {
16 | "inputs": [],
17 | "name": "version",
18 | "outputs": [
19 | {
20 | "internalType": "bytes32",
21 | "name": "",
22 | "type": "bytes32"
23 | }
24 | ],
25 | "stateMutability": "pure",
26 | "type": "function"
27 | }
28 | ]
--------------------------------------------------------------------------------
/abis/IPausable.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "name": "paused",
5 | "outputs": [
6 | {
7 | "internalType": "bool",
8 | "name": "",
9 | "type": "bool"
10 | }
11 | ],
12 | "stateMutability": "view",
13 | "type": "function"
14 | }
15 | ]
--------------------------------------------------------------------------------
/abis/IPriceOracle.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "token",
7 | "type": "address"
8 | },
9 | {
10 | "internalType": "uint256",
11 | "name": "amountIn",
12 | "type": "uint256"
13 | }
14 | ],
15 | "name": "consult",
16 | "outputs": [
17 | {
18 | "internalType": "uint256",
19 | "name": "amountOut",
20 | "type": "uint256"
21 | }
22 | ],
23 | "stateMutability": "view",
24 | "type": "function"
25 | },
26 | {
27 | "inputs": [
28 | {
29 | "internalType": "uint256",
30 | "name": "amountIn",
31 | "type": "uint256"
32 | }
33 | ],
34 | "name": "consultPair",
35 | "outputs": [
36 | {
37 | "internalType": "uint256",
38 | "name": "",
39 | "type": "uint256"
40 | }
41 | ],
42 | "stateMutability": "view",
43 | "type": "function"
44 | },
45 | {
46 | "inputs": [],
47 | "name": "update",
48 | "outputs": [],
49 | "stateMutability": "nonpayable",
50 | "type": "function"
51 | }
52 | ]
--------------------------------------------------------------------------------
/abis/IRecoverable.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "sendTo",
7 | "type": "address"
8 | }
9 | ],
10 | "name": "recoverEther",
11 | "outputs": [],
12 | "stateMutability": "nonpayable",
13 | "type": "function"
14 | },
15 | {
16 | "inputs": [
17 | {
18 | "internalType": "address",
19 | "name": "token",
20 | "type": "address"
21 | },
22 | {
23 | "internalType": "address",
24 | "name": "sendTo",
25 | "type": "address"
26 | }
27 | ],
28 | "name": "recoverToken",
29 | "outputs": [],
30 | "stateMutability": "nonpayable",
31 | "type": "function"
32 | },
33 | {
34 | "inputs": [],
35 | "name": "s",
36 | "outputs": [
37 | {
38 | "internalType": "contract IStore",
39 | "name": "",
40 | "type": "address"
41 | }
42 | ],
43 | "stateMutability": "view",
44 | "type": "function"
45 | }
46 | ]
--------------------------------------------------------------------------------
/abis/IUniswapV2FactoryLike.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "address",
8 | "name": "token0",
9 | "type": "address"
10 | },
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "token1",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "pair",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "uint256",
26 | "name": "",
27 | "type": "uint256"
28 | }
29 | ],
30 | "name": "PairCreated",
31 | "type": "event"
32 | },
33 | {
34 | "inputs": [
35 | {
36 | "internalType": "address",
37 | "name": "tokenA",
38 | "type": "address"
39 | },
40 | {
41 | "internalType": "address",
42 | "name": "tokenB",
43 | "type": "address"
44 | }
45 | ],
46 | "name": "getPair",
47 | "outputs": [
48 | {
49 | "internalType": "address",
50 | "name": "pair",
51 | "type": "address"
52 | }
53 | ],
54 | "stateMutability": "view",
55 | "type": "function"
56 | }
57 | ]
--------------------------------------------------------------------------------
/abis/IUniswapV2PairLike.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "name": "getReserves",
5 | "outputs": [
6 | {
7 | "internalType": "uint112",
8 | "name": "reserve0",
9 | "type": "uint112"
10 | },
11 | {
12 | "internalType": "uint112",
13 | "name": "reserve1",
14 | "type": "uint112"
15 | },
16 | {
17 | "internalType": "uint32",
18 | "name": "blockTimestampLast",
19 | "type": "uint32"
20 | }
21 | ],
22 | "stateMutability": "view",
23 | "type": "function"
24 | },
25 | {
26 | "inputs": [],
27 | "name": "token0",
28 | "outputs": [
29 | {
30 | "internalType": "address",
31 | "name": "",
32 | "type": "address"
33 | }
34 | ],
35 | "stateMutability": "view",
36 | "type": "function"
37 | },
38 | {
39 | "inputs": [],
40 | "name": "token1",
41 | "outputs": [
42 | {
43 | "internalType": "address",
44 | "name": "",
45 | "type": "address"
46 | }
47 | ],
48 | "stateMutability": "view",
49 | "type": "function"
50 | },
51 | {
52 | "inputs": [],
53 | "name": "totalSupply",
54 | "outputs": [
55 | {
56 | "internalType": "uint256",
57 | "name": "",
58 | "type": "uint256"
59 | }
60 | ],
61 | "stateMutability": "view",
62 | "type": "function"
63 | }
64 | ]
--------------------------------------------------------------------------------
/audits/001-blocksec.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neptune-mutual-blue/protocol/1256dfc57bd727bdba171d34eabd4176db89f999/audits/001-blocksec.pdf
--------------------------------------------------------------------------------
/audits/002-open-zeppelin.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neptune-mutual-blue/protocol/1256dfc57bd727bdba171d34eabd4176db89f999/audits/002-open-zeppelin.pdf
--------------------------------------------------------------------------------
/contracts/core/delegates/VaultDelegate.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "./VaultDelegateWithFlashLoan.sol";
6 |
7 | /**
8 | * @title Vault Delegate
9 | *
10 | * @dev Because vaults cannot be upgraded individually, all vaults delegate some logic to this contract.
11 | *
12 | * @notice Liquidity providers can earn fees by adding stablecoin liquidity
13 | * to any cover contract. The cover pool is collectively owned by liquidity providers
14 | * where fees automatically get accumulated and compounded.
15 | *
16 | *
17 | *
18 | * **Fees:**
19 | *
20 | * - Cover fees paid in stablecoin get added to the liquidity pool.
21 | * - The protocol supplies a small portion of idle assets to third-party lending protocols.
22 | * - Flash loan interest also gets added back to the pool.
23 | * - Cover creators can donate a small portion of their revenue as a reassurance fund
24 | * to protect liquidity providers. This assists liquidity providers in the event of an exploit
25 | * by preventing pool depletion.
26 | *
27 | */
28 | contract VaultDelegate is VaultDelegateWithFlashLoan {
29 | constructor(IStore store) VaultDelegateBase(store) {} // solhint-disable-line
30 | }
31 |
--------------------------------------------------------------------------------
/contracts/core/governance/resolution/Resolution.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./Unstakable.sol";
5 | import "../../../interfaces/IResolution.sol";
6 |
7 | /**
8 | *
9 | * @title Resolution Contract
10 | * @dev This contract enables governance agents or admins to resolve
11 | * actively-reporting cover products. Once a resolution occurs, the
12 | * NPM token holders who voted for the valid camp can unstake
13 | * their stakes after resolution and before finalization
14 | * with additional rewards.
15 | *
16 | */
17 | contract Resolution is IResolution, Unstakable {
18 | constructor(IStore store) Recoverable(store) {} // solhint-disable-line
19 |
20 | /**
21 | * @dev Version number of this contract
22 | */
23 | function version() external pure override returns (bytes32) {
24 | return "v0.1";
25 | }
26 |
27 | /**
28 | * @dev Name of this contract
29 | */
30 | function getName() external pure override returns (bytes32) {
31 | return ProtoUtilV1.CNAME_RESOLUTION;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/core/liquidity/VaultBase.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
4 | import "../Recoverable.sol";
5 | import "../../interfaces/IVaultDelegate.sol";
6 | import "../../interfaces/IVault.sol";
7 | import "../../libraries/NTransferUtilV2.sol";
8 |
9 | pragma solidity ^0.8.0;
10 |
11 | /**
12 | * @title Vault Base Contract
13 | */
14 | abstract contract VaultBase is ERC20, Recoverable, IVault {
15 | using ProtoUtilV1 for IStore;
16 | using RegistryLibV1 for IStore;
17 | using NTransferUtilV2 for IERC20;
18 |
19 | bytes32 public override key;
20 | address public override sc;
21 |
22 | /**
23 | * @dev Constructs this contract
24 | *
25 | * @param store Provide store instance
26 | * @param coverKey Provide a cover key that doesn't have a vault deployed
27 | * @param tokenName Enter the token name of the POD. Example: `Uniswap nDAI` or `Uniswap nUSDC`
28 | * @param tokenSymbol Enter the token symbol of the POD. Example: UNI-NDAI or `UNI-NUSDC`.
29 | * @param stablecoin Provide an instance of the stablecoin this vault supports.
30 | *
31 | */
32 | constructor(
33 | IStore store,
34 | bytes32 coverKey,
35 | string memory tokenName,
36 | string memory tokenSymbol,
37 | IERC20 stablecoin
38 | ) ERC20(tokenName, tokenSymbol) Recoverable(store) {
39 | key = coverKey;
40 | sc = address(stablecoin);
41 | }
42 |
43 | /**
44 | * @dev Returns the delegate contract instance
45 | */
46 | function delegate() public view returns (IVaultDelegate) {
47 | return IVaultDelegate(s.getVaultDelegate());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/contracts/core/token/Delayable.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity ^0.8.0;
3 |
4 | import "openzeppelin-solidity/contracts/governance/TimelockController.sol";
5 | import "./WithRecovery.sol";
6 |
7 | contract Delayable is TimelockController, WithRecovery {
8 | constructor(
9 | uint256 minDelay,
10 | address[] memory proposers,
11 | address[] memory executors
12 | ) TimelockController(minDelay, proposers, executors) {} // solhint-disable-line
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/core/token/Treasury.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import {IERC20} from "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
6 | import {WithRecovery} from "./WithRecovery.sol";
7 | import {WithPausability} from "./WithPausability.sol";
8 | import {SafeERC20} from "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
9 |
10 | contract Treasury is WithPausability, WithRecovery {
11 | using SafeERC20 for IERC20;
12 |
13 | constructor(address timelockOrOwner) {
14 | require(timelockOrOwner != address(0), "Invalid owner");
15 | super._transferOwnership(timelockOrOwner);
16 | }
17 |
18 | function transferMany(IERC20 token, address[] calldata receivers, uint256[] calldata amounts) external onlyOwner whenNotPaused {
19 | require(receivers.length > 0, "No receiver");
20 | require(receivers.length == amounts.length, "Invalid args");
21 | require(token.balanceOf(address(this)) >= _sumOf(amounts), "Insufficient Balance");
22 |
23 | for (uint256 i = 0; i < receivers.length; i++) {
24 | token.safeTransfer(receivers[i], amounts[i]);
25 | }
26 | }
27 |
28 | function _sumOf(uint256[] calldata amounts) private pure returns (uint256 total) {
29 | for (uint256 i = 0; i < amounts.length; i++) {
30 | total += amounts[i];
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/core/token/WithPausability.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "openzeppelin-solidity/contracts/security/Pausable.sol";
6 | import "openzeppelin-solidity/contracts/access/Ownable.sol";
7 |
8 | abstract contract WithPausability is Pausable, Ownable {
9 | mapping(address => bool) public pausers;
10 |
11 | event PausersSet(address indexed addedBy, address[] accounts, bool[] statuses);
12 |
13 | /**
14 | *
15 | * @dev Accepts a list of accounts and their respective statuses for addition or removal as pausers.
16 | *
17 | * @custom:suppress-reentrancy Risk tolerable. Can only be called by the owner.
18 | * @custom:suppress-address-trust-issue Risk tolerable.
19 | */
20 | function setPausers(address[] calldata accounts, bool[] calldata statuses) external onlyOwner whenNotPaused {
21 | require(accounts.length > 0, "No pauser specified");
22 | require(accounts.length == statuses.length, "Invalid args");
23 |
24 | for (uint256 i = 0; i < accounts.length; i++) {
25 | pausers[accounts[i]] = statuses[i];
26 | }
27 |
28 | emit PausersSet(msg.sender, accounts, statuses);
29 | }
30 |
31 | /**
32 | * @dev Pauses the token
33 | *
34 | * @custom:suppress-reentrancy Risk tolerable. Can only be called by a pauser.
35 | *
36 | */
37 | function pause() external {
38 | require(pausers[msg.sender], "Forbidden");
39 | super._pause();
40 | }
41 |
42 | /**
43 | * @dev Unpauses the token
44 | *
45 | * @custom:suppress-reentrancy Risk tolerable. Can only be called by the owner.
46 | *
47 | */
48 | function unpause() external onlyOwner {
49 | super._unpause();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/contracts/core/token/WithRecovery.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
6 | import "openzeppelin-solidity/contracts/access/Ownable.sol";
7 |
8 | abstract contract WithRecovery is Ownable {
9 | using SafeERC20 for IERC20;
10 |
11 | /**
12 | * @dev Recover all Ether held by the contract.
13 | *
14 | * @custom:suppress-pausable Risk tolerable because of the ACL
15 | *
16 | */
17 | function recoverEther(address sendTo) external onlyOwner {
18 | // slither-disable-next-line low-level-calls
19 | (bool success, ) = payable(sendTo).call{value: address(this).balance}(""); // solhint-disable-line avoid-low-level-calls
20 | require(success, "Recipient may have reverted");
21 | }
22 |
23 | /**
24 | * @dev Recover an ERC-20 compatible token sent to this contract.
25 | * @param malicious ERC-20 The address of the token contract
26 | * @param sendTo The address that receives the recovered tokens
27 | *
28 | * @custom:suppress-pausable Risk tolerable because of the ACL
29 | *
30 | */
31 | function recoverToken(IERC20 malicious, address sendTo) external onlyOwner {
32 | malicious.safeTransfer(sendTo, malicious.balanceOf(address(this)));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/contracts/dependencies/compound/ICompoundERC20DelegatorLike.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: agpl-3.0
2 | pragma solidity ^0.8.0;
3 |
4 | // https://github.com/compound-finance/compound-protocol/blob/master/contracts/CErc20Delegator.sol
5 | interface ICompoundERC20DelegatorLike {
6 | /**
7 | * @notice Sender supplies assets into the market and receives cTokens in exchange
8 | * @dev Accrues interest whether or not the operation succeeds, unless reverted
9 | * @param mintAmount The amount of the underlying asset to supply
10 | * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
11 | */
12 | function mint(uint256 mintAmount) external returns (uint256);
13 |
14 | /**
15 | * @notice Sender redeems cTokens in exchange for the underlying asset
16 | * @dev Accrues interest whether or not the operation succeeds, unless reverted
17 | * @param redeemTokens The number of cTokens to redeem into underlying
18 | * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
19 | */
20 | function redeem(uint256 redeemTokens) external returns (uint256);
21 | }
22 |
--------------------------------------------------------------------------------
/contracts/dependencies/uniswap-v2/IUniswapV2FactoryLike.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IUniswapV2FactoryLike {
6 | event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
7 |
8 | function getPair(address tokenA, address tokenB) external view returns (address pair);
9 | }
10 |
--------------------------------------------------------------------------------
/contracts/dependencies/uniswap-v2/IUniswapV2PairLike.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IUniswapV2PairLike {
6 | function token0() external view returns (address);
7 |
8 | function token1() external view returns (address);
9 |
10 | function totalSupply() external view returns (uint256);
11 |
12 | function getReserves()
13 | external
14 | view
15 | returns (
16 | uint112 reserve0,
17 | uint112 reserve1,
18 | uint32 blockTimestampLast
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/dependencies/uniswap-v2/IUniswapV2RouterLike.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IUniswapV2RouterLike {
6 | function factory() external view returns (address);
7 |
8 | function getAmountOut(
9 | uint256 amountIn,
10 | uint256 reserveIn,
11 | uint256 reserveOut
12 | ) external pure returns (uint256 amountOut);
13 |
14 | function getAmountIn(
15 | uint256 amountOut,
16 | uint256 reserveIn,
17 | uint256 reserveOut
18 | ) external pure returns (uint256 amountIn);
19 |
20 | function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
21 |
22 | function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
23 |
24 | function quote(
25 | uint256 amountA,
26 | uint256 reserveA,
27 | uint256 reserveB
28 | ) external pure returns (uint256 amountB);
29 |
30 | function addLiquidity(
31 | address tokenA,
32 | address tokenB,
33 | uint256 amountADesired,
34 | uint256 amountBDesired,
35 | uint256 amountAMin,
36 | uint256 amountBMin,
37 | address to,
38 | uint256 deadline
39 | )
40 | external
41 | returns (
42 | uint256 amountA,
43 | uint256 amountB,
44 | uint256 liquidity
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/contracts/fakes/Destroyable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | contract Destroyable {
6 | constructor() payable {} // solhint-disable-line
7 |
8 | // slither-disable-next-line suicidal
9 | function destroy(address payable _recipient) public {
10 | selfdestruct(_recipient);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeAaveLendingPool.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../dependencies/aave/IAaveV2LendingPoolLike.sol";
5 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
6 | import "./FakeToken.sol";
7 |
8 | contract FakeAaveLendingPool is IAaveV2LendingPoolLike, ERC20 {
9 | FakeToken public aToken;
10 |
11 | constructor(FakeToken _aToken) ERC20("aStablecoin", "aStablecoin") {
12 | aToken = _aToken;
13 | }
14 |
15 | function deposit(
16 | address asset,
17 | uint256 amount,
18 | address,
19 | uint16
20 | ) external override {
21 | IERC20(asset).transferFrom(msg.sender, address(this), amount);
22 | aToken.mint(amount);
23 | aToken.transfer(msg.sender, amount);
24 | }
25 |
26 | function withdraw(
27 | address asset,
28 | uint256 amount,
29 | address to
30 | ) external override returns (uint256) {
31 | aToken.transferFrom(msg.sender, address(this), amount);
32 |
33 | FakeToken stablecoin = FakeToken(asset);
34 |
35 | uint256 interest = (amount * 10) / 100;
36 | stablecoin.mint(interest);
37 |
38 | stablecoin.transfer(to, amount + interest);
39 |
40 | return amount;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/contracts/fakes/FakePriceOracle.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../interfaces/IPriceOracle.sol";
5 |
6 | contract FakePriceOracle is IPriceOracle {
7 | uint256 private _counter = 0;
8 |
9 | function update() external override {
10 | _counter++;
11 | }
12 |
13 | function consult(address, uint256 amountIn) external pure override returns (uint256) {
14 | return amountIn * 2;
15 | }
16 |
17 | function consultPair(uint256 amountIn) external pure override returns (uint256) {
18 | return amountIn;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeRecoverable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../core/Recoverable.sol";
5 |
6 | contract FakeRecoverable is Recoverable {
7 | constructor(IStore s) Recoverable(s) {} // solhint-disable-line
8 | }
9 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeToken.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
5 |
6 | contract FakeToken is ERC20 {
7 | address public immutable deployer;
8 | mapping(address => bool) public minters;
9 | uint8 private immutable _decimals;
10 |
11 | function addMinter(address account, bool flag) public onlyDeployer {
12 | minters[account] = flag;
13 | }
14 |
15 | modifier onlyDeployer() {
16 | require(msg.sender == deployer, "Forbidden");
17 | _;
18 | }
19 |
20 | constructor(
21 | string memory name,
22 | string memory symbol,
23 | uint256 supply,
24 | uint8 decimalPlaces
25 | ) ERC20(name, symbol) {
26 | require(decimalPlaces > 0, "Invalid decimal places value");
27 |
28 | super._mint(msg.sender, supply);
29 | deployer = msg.sender;
30 | minters[msg.sender] = true;
31 | _decimals = decimalPlaces;
32 | }
33 |
34 | function decimals() public view virtual override returns (uint8) {
35 | return _decimals;
36 | }
37 |
38 | function mint(uint256 amount) external {
39 | if (amount > 2000 * (10**_decimals)) {
40 | require(minters[msg.sender], "Please specify a smaller value");
41 | }
42 |
43 | super._mint(msg.sender, amount);
44 | }
45 |
46 | function burn(uint256 amount) external {
47 | super._burn(msg.sender, amount);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeUniswapPair.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../dependencies/uniswap-v2/IUniswapV2PairLike.sol";
5 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
6 |
7 | contract FakeUniswapPair is IUniswapV2PairLike, ERC20 {
8 | address public override token0;
9 | address public override token1;
10 |
11 | constructor(address _token0, address _token1) ERC20("PAIR", "PAIR") {
12 | token0 = _token0;
13 | token1 = _token1;
14 |
15 | super._mint(msg.sender, 100000 ether);
16 | }
17 |
18 | function totalSupply() public view override(ERC20, IUniswapV2PairLike) returns (uint256) {
19 | return super.totalSupply();
20 | }
21 |
22 | function getReserves()
23 | external
24 | view
25 | override
26 | returns (
27 | uint112 reserve0,
28 | uint112 reserve1,
29 | uint32 blockTimestampLast
30 | )
31 | {
32 | reserve0 = 100000 ether;
33 | reserve1 = 50000 ether;
34 | blockTimestampLast = uint32(block.timestamp - 1 hours); // solhint-disable-line
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeUniswapV2FactoryLike.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../dependencies/uniswap-v2/IUniswapV2FactoryLike.sol";
5 |
6 | contract FakeUniswapV2FactoryLike is IUniswapV2FactoryLike {
7 | address public pair;
8 |
9 | constructor(address _pair) {
10 | pair = _pair;
11 | }
12 |
13 | function getPair(address, address) external view override returns (address) {
14 | return pair;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/contracts/fakes/FakeUniswapV2PairLike.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../dependencies/uniswap-v2/IUniswapV2PairLike.sol";
5 |
6 | contract FakeUniswapV2PairLike is IUniswapV2PairLike {
7 | address public override token0;
8 | address public override token1;
9 |
10 | constructor(address _token0, address _token1) {
11 | token0 = _token0;
12 | token1 = _token1;
13 | }
14 |
15 | function totalSupply() external pure override returns (uint256) {
16 | return 100 ether;
17 | }
18 |
19 | function getReserves()
20 | external
21 | view
22 | override
23 | returns (
24 | uint112 reserve0,
25 | uint112 reserve1,
26 | uint32 blockTimestampLast
27 | )
28 | {
29 | reserve0 = 200 ether;
30 | reserve1 = 100 ether;
31 | blockTimestampLast = uint32(block.timestamp); // solhint-disable-line
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/fakes/FaultyAaveLendingPool.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../dependencies/aave/IAaveV2LendingPoolLike.sol";
5 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
6 | import "./FakeToken.sol";
7 |
8 | contract FaultyAaveLendingPool is IAaveV2LendingPoolLike, ERC20 {
9 | FakeToken public aToken;
10 |
11 | constructor(FakeToken _aToken) ERC20("aStablecoin", "aStablecoin") {
12 | aToken = _aToken;
13 | }
14 |
15 | function deposit(
16 | address asset,
17 | uint256 amount,
18 | address,
19 | uint16
20 | ) external override {
21 | IERC20(asset).transferFrom(msg.sender, address(this), amount);
22 | }
23 |
24 | function withdraw(
25 | address, /*asset*/
26 | uint256 amount,
27 | address /*to*/
28 | ) external override returns (uint256) {
29 | aToken.transferFrom(msg.sender, address(this), amount);
30 | return amount;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/fakes/ForceEther.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity ^0.8.0;
3 |
4 | contract ForceEther {
5 | event Received(address indexed account, uint256 amount);
6 |
7 | receive() external payable {
8 | emit Received(msg.sender, msg.value);
9 | }
10 |
11 | function destruct(address payable to) external {
12 | selfdestruct(to);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/contracts/fakes/InvalidStrategy.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "../core/liquidity/strategies/AaveStrategy.sol";
6 |
7 | contract InvalidStrategy is AaveStrategy {
8 | constructor(
9 | IStore _s,
10 | IAaveV2LendingPoolLike _lendingPool,
11 | address _aToken
12 | ) AaveStrategy(_s, _lendingPool, _aToken) {} // solhint-disable-line
13 |
14 | function getWeight() external pure override returns (uint256) {
15 | return 20_000; // 100%
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/contracts/fakes/MaliciousToken.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
5 |
6 | contract MaliciousToken is ERC20 {
7 | address public constant BAD = 0x0000000000000000000000000000000000000010;
8 |
9 | constructor() ERC20("Malicious Token", "MAL") {} // solhint-disable-line
10 |
11 | function mint(address account, uint256 amount) external {
12 | super._mint(account, amount);
13 | }
14 |
15 | function transfer(address recipient, uint256 amount) public override returns (bool) {
16 | _transfer(msg.sender, BAD, (amount * 10) / 100);
17 | _transfer(msg.sender, recipient, (amount * 90) / 100);
18 |
19 | return true;
20 | }
21 |
22 | function transferFrom(
23 | address sender,
24 | address recipient,
25 | uint256 amount
26 | ) public override returns (bool) {
27 | super.transferFrom(sender, BAD, (amount * 10) / 100);
28 | super.transferFrom(sender, recipient, (amount * 90) / 100);
29 |
30 | return true;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/fakes/NTransferUtilV2Intermediate.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
5 | import "../libraries/NTransferUtilV2.sol";
6 |
7 | contract NTransferUtilV2Intermediate {
8 | using NTransferUtilV2 for IERC20;
9 |
10 | function iTransfer(
11 | IERC20 token,
12 | address recipient,
13 | uint256 amount
14 | ) external {
15 | token.ensureTransfer(recipient, amount);
16 | }
17 |
18 | function iTransferFrom(
19 | IERC20 token,
20 | address sender,
21 | address recipient,
22 | uint256 amount
23 | ) external {
24 | token.ensureTransferFrom(sender, recipient, amount);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/interfaces/IBondPool.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IMember.sol";
5 |
6 | interface IBondPool is IMember {
7 | struct BondPoolInfoType {
8 | address lpToken;
9 | uint256 marketPrice;
10 | uint256 discountRate;
11 | uint256 vestingTerm;
12 | uint256 maxBond;
13 | uint256 totalNpmAllocated;
14 | uint256 totalNpmDistributed;
15 | uint256 npmAvailable;
16 | uint256 bondContribution;
17 | uint256 claimable;
18 | uint256 unlockDate;
19 | }
20 |
21 | struct SetupBondPoolArgs {
22 | address lpToken;
23 | address treasury;
24 | uint256 bondDiscountRate;
25 | uint256 maxBondAmount;
26 | uint256 vestingTerm;
27 | uint256 npmToTopUpNow;
28 | }
29 |
30 | event BondPoolSetup(SetupBondPoolArgs args);
31 | event BondCreated(address indexed account, uint256 lpTokens, uint256 npmToVest, uint256 unlockDate);
32 | event BondClaimed(address indexed account, uint256 amount);
33 |
34 | function setup(SetupBondPoolArgs calldata args) external;
35 |
36 | function createBond(uint256 lpTokens, uint256 minNpmDesired) external;
37 |
38 | function claimBond() external;
39 |
40 | function getNpmMarketPrice() external view returns (uint256);
41 |
42 | function calculateTokensForLp(uint256 lpTokens) external view returns (uint256);
43 |
44 | function getInfo(address forAccount) external view returns (BondPoolInfoType memory info);
45 | }
46 |
--------------------------------------------------------------------------------
/contracts/interfaces/IClaimsProcessor.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IMember.sol";
5 |
6 | interface IClaimsProcessor is IMember {
7 | event Claimed(
8 | address cxToken,
9 | bytes32 indexed coverKey,
10 | bytes32 indexed productKey,
11 | uint256 incidentDate,
12 | address indexed account,
13 | address reporter,
14 | uint256 amount,
15 | uint256 reporterFee,
16 | uint256 platformFee,
17 | uint256 claimed
18 | );
19 | event ClaimPeriodSet(bytes32 indexed coverKey, uint256 previous, uint256 current);
20 | event BlacklistSet(bytes32 indexed coverKey, bytes32 indexed productKey, uint256 indexed incidentDate, address account, bool status);
21 |
22 | function claim(
23 | address cxToken,
24 | bytes32 coverKey,
25 | bytes32 productKey,
26 | uint256 incidentDate,
27 | uint256 amount
28 | ) external;
29 |
30 | function validate(
31 | address cxToken,
32 | bytes32 coverKey,
33 | bytes32 productKey,
34 | uint256 incidentDate,
35 | uint256 amount
36 | ) external view returns (bool);
37 |
38 | function setClaimPeriod(bytes32 coverKey, uint256 value) external;
39 |
40 | function getClaimExpiryDate(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
41 |
42 | function setBlacklist(
43 | bytes32 coverKey,
44 | bytes32 productKey,
45 | uint256 incidentDate,
46 | address[] calldata accounts,
47 | bool[] calldata statuses
48 | ) external;
49 |
50 | function isBlacklisted(
51 | bytes32 coverKey,
52 | bytes32 productKey,
53 | uint256 incidentDate,
54 | address account
55 | ) external view returns (bool);
56 | }
57 |
--------------------------------------------------------------------------------
/contracts/interfaces/ICoverReassurance.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IMember.sol";
5 |
6 | interface ICoverReassurance is IMember {
7 | event ReassuranceAdded(bytes32 indexed coverKey, address indexed onBehalfOf, uint256 amount);
8 | event WeightSet(bytes32 indexed coverKey, uint256 weight);
9 | event PoolCapitalized(bytes32 indexed coverKey, bytes32 indexed productKey, uint256 indexed incidentDate, uint256 amount);
10 |
11 | /**
12 | * @dev Adds reassurance to the specified cover contract
13 | * @param coverKey Enter the cover key
14 | * @param onBehalfOf Enter the account on behalf of which you are adding reassurance.
15 | * @param amount Enter the amount you would like to supply
16 | */
17 | function addReassurance(
18 | bytes32 coverKey,
19 | address onBehalfOf,
20 | uint256 amount
21 | ) external;
22 |
23 | function setWeight(bytes32 coverKey, uint256 weight) external;
24 |
25 | function capitalizePool(
26 | bytes32 coverKey,
27 | bytes32 productKey,
28 | uint256 incidentDate
29 | ) external;
30 |
31 | /**
32 | * @dev Gets the reassurance amount of the specified cover contract
33 | * @param coverKey Enter the cover key
34 | */
35 | function getReassurance(bytes32 coverKey) external view returns (uint256);
36 | }
37 |
--------------------------------------------------------------------------------
/contracts/interfaces/ICoverStake.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IMember.sol";
5 |
6 | interface ICoverStake is IMember {
7 | event StakeAdded(bytes32 indexed coverKey, address indexed account, uint256 amount);
8 | event StakeRemoved(bytes32 indexed coverKey, address indexed account, uint256 amount);
9 | event FeeBurned(bytes32 indexed coverKey, uint256 amount);
10 |
11 | /**
12 | * @dev Increase the stake of the given cover pool
13 | * @param coverKey Enter the cover key
14 | * @param account Enter the account from where the NPM tokens will be transferred
15 | * @param amount Enter the amount of stake
16 | * @param fee Enter the fee amount. Note: do not enter the fee if you are directly calling this function.
17 | */
18 | function increaseStake(
19 | bytes32 coverKey,
20 | address account,
21 | uint256 amount,
22 | uint256 fee
23 | ) external;
24 |
25 | /**
26 | * @dev Decreases the stake from the given cover pool
27 | * @param coverKey Enter the cover key
28 | * @param amount Enter the amount of stake to decrease
29 | */
30 | function decreaseStake(bytes32 coverKey, uint256 amount) external;
31 |
32 | /**
33 | * @dev Gets the stake of an account for the given cover key
34 | * @param coverKey Enter the cover key
35 | * @param account Specify the account to obtain the stake of
36 | * @return Returns the total stake of the specified account on the given cover key
37 | */
38 | function stakeOf(bytes32 coverKey, address account) external view returns (uint256);
39 | }
40 |
--------------------------------------------------------------------------------
/contracts/interfaces/ICxToken.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
4 |
5 | pragma solidity ^0.8.0;
6 |
7 | interface ICxToken is IERC20 {
8 | event CoverageStartSet(uint256 policyId, bytes32 coverKey, bytes32 productKey, address account, uint256 effectiveFrom, uint256 amount);
9 |
10 | function mint(
11 | uint256 policyId,
12 | bytes32 coverKey,
13 | bytes32 productKey,
14 | address to,
15 | uint256 amount
16 | ) external;
17 |
18 | function burn(uint256 amount) external;
19 |
20 | function createdOn() external view returns (uint256);
21 |
22 | function expiresOn() external view returns (uint256);
23 |
24 | // slither-disable-next-line naming-convention
25 | function COVER_KEY() external view returns (bytes32); // solhint-disable
26 |
27 | // slither-disable-next-line naming-convention
28 | function PRODUCT_KEY() external view returns (bytes32); // solhint-disable
29 |
30 | function getCoverageStartsFrom(address account, uint256 date) external view returns (uint256);
31 |
32 | function getClaimablePolicyOf(address account) external view returns (uint256);
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/interfaces/ICxTokenFactory.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IStore.sol";
5 | import "./IMember.sol";
6 |
7 | interface ICxTokenFactory is IMember {
8 | event CxTokenDeployed(address cxToken, IStore store, bytes32 indexed coverKey, bytes32 indexed productKey, string tokenName, uint256 indexed expiryDate);
9 |
10 | function deploy(
11 | bytes32 coverKey,
12 | bytes32 productKey,
13 | string calldata tokenName,
14 | uint256 expiryDate
15 | ) external returns (address);
16 | }
17 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC20Detailed.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
4 |
5 | pragma solidity ^0.8.0;
6 |
7 | interface IERC20Detailed is IERC20 {
8 | function name() external view returns (string memory);
9 |
10 | function symbol() external view returns (string memory);
11 |
12 | function decimals() external view returns (uint8);
13 |
14 | function mint(uint256 amount) external;
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/interfaces/IFinalization.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IFinalization {
6 | event Finalized(bytes32 indexed coverKey, bytes32 indexed productKey, address finalizer, uint256 indexed incidentDate);
7 |
8 | function finalize(
9 | bytes32 coverKey,
10 | bytes32 productKey,
11 | uint256 incidentDate
12 | ) external;
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/interfaces/IGovernance.sol:
--------------------------------------------------------------------------------
1 | /* solhint-disable function-max-lines */
2 | // Neptune Mutual Protocol (https://neptunemutual.com)
3 | // SPDX-License-Identifier: BUSL-1.1
4 | pragma solidity ^0.8.0;
5 | import "./IReporter.sol";
6 | import "./IWitness.sol";
7 | import "./IMember.sol";
8 |
9 | // solhint-disable-next-line
10 | interface IGovernance is IMember, IReporter, IWitness {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/interfaces/ILendingStrategy.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
4 | import "./IMember.sol";
5 |
6 | pragma solidity ^0.8.0;
7 |
8 | interface ILendingStrategy is IMember {
9 | struct LendingStrategyInfoType {
10 | uint256 deposits;
11 | uint256 withdrawals;
12 | }
13 |
14 | event LogDeposit(bytes32 indexed name, uint256 counter, uint256 amount, uint256 certificateReceived, uint256 depositTotal, uint256 withdrawalTotal);
15 | event Deposited(bytes32 indexed key, address indexed onBehalfOf, uint256 stablecoinDeposited, uint256 certificateTokenIssued);
16 | event LogWithdrawal(bytes32 indexed name, uint256 counter, uint256 stablecoinWithdrawn, uint256 certificateRedeemed, uint256 depositTotal, uint256 withdrawalTotal);
17 | event Withdrawn(bytes32 indexed key, address indexed sendTo, uint256 stablecoinWithdrawn, uint256 certificateTokenRedeemed);
18 | event Drained(IERC20 indexed asset, uint256 amount);
19 |
20 | function getKey() external pure returns (bytes32);
21 |
22 | function getWeight() external pure returns (uint256);
23 |
24 | function getDepositAsset() external view returns (IERC20);
25 |
26 | function getDepositCertificate() external view returns (IERC20);
27 |
28 | /**
29 | * @dev Gets info of this strategy by cover key
30 | * @param coverKey Enter the cover key
31 | */
32 | function getInfo(bytes32 coverKey) external view returns (LendingStrategyInfoType memory info);
33 |
34 | function deposit(bytes32 coverKey, uint256 amount) external returns (uint256 certificateReceived);
35 |
36 | function withdraw(bytes32 coverKey) external returns (uint256 stablecoinWithdrawn);
37 | }
38 |
--------------------------------------------------------------------------------
/contracts/interfaces/ILiquidityEngine.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
4 | import "./IMember.sol";
5 | import "./IVault.sol";
6 |
7 | pragma solidity ^0.8.0;
8 |
9 | interface ILiquidityEngine is IMember {
10 | event StrategyAdded(address indexed strategy);
11 | event StrategyDisabled(address indexed strategy);
12 | event StrategyDeleted(address indexed strategy);
13 | event RiskPoolingPeriodSet(bytes32 indexed coverKey, uint256 lendingPeriod, uint256 withdrawalWindow);
14 | event LiquidityStateUpdateIntervalSet(uint256 duration);
15 | event MaxLendingRatioSet(uint256 ratio);
16 |
17 | function addStrategies(address[] calldata strategies) external;
18 |
19 | function disableStrategy(address strategy) external;
20 |
21 | function deleteStrategy(address strategy) external;
22 |
23 | function setRiskPoolingPeriods(
24 | bytes32 coverKey,
25 | uint256 lendingPeriod,
26 | uint256 withdrawalWindow
27 | ) external;
28 |
29 | function getRiskPoolingPeriods(bytes32 coverKey) external view returns (uint256 lendingPeriod, uint256 withdrawalWindow);
30 |
31 | function setLiquidityStateUpdateInterval(uint256 value) external;
32 |
33 | function setMaxLendingRatio(uint256 ratio) external;
34 |
35 | function getMaxLendingRatio() external view returns (uint256 ratio);
36 |
37 | function getDisabledStrategies() external view returns (address[] memory strategies);
38 |
39 | function getActiveStrategies() external view returns (address[] memory strategies);
40 |
41 | function addBulkLiquidity(IVault.AddLiquidityArgs[] calldata args) external;
42 | }
43 |
--------------------------------------------------------------------------------
/contracts/interfaces/IMember.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IMember {
6 | /**
7 | * @dev Version number of this contract
8 | */
9 | function version() external pure returns (bytes32);
10 |
11 | /**
12 | * @dev Name of this contract
13 | */
14 | function getName() external pure returns (bytes32);
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPausable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IPausable {
6 | function paused() external view returns (bool);
7 | }
8 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPolicyAdmin.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IMember.sol";
5 |
6 | interface IPolicyAdmin is IMember {
7 | event CoverPolicyRateSet(bytes32 indexed coverKey, uint256 floor, uint256 ceiling);
8 | event CoverageLagSet(bytes32 indexed coverKey, uint256 window);
9 |
10 | /**
11 | * @dev Sets policy rates for the given cover key. This feature is only accessible by owner or protocol owner.
12 | * @param floor The lowest cover fee rate for this cover
13 | * @param ceiling The highest cover fee rate for this cover
14 | */
15 | function setPolicyRatesByKey(
16 | bytes32 coverKey,
17 | uint256 floor,
18 | uint256 ceiling
19 | ) external;
20 |
21 | /**
22 | * @dev Gets the cover policy rates for the given cover key
23 | */
24 | function getPolicyRates(bytes32 coverKey) external view returns (uint256 floor, uint256 ceiling);
25 |
26 | function setCoverageLag(bytes32 coverKey, uint256 window) external;
27 |
28 | function getCoverageLag(bytes32 coverKey) external view returns (uint256);
29 | }
30 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPriceOracle.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IPriceOracle {
6 | function update() external;
7 |
8 | function consult(address token, uint256 amountIn) external view returns (uint256 amountOut);
9 |
10 | function consultPair(uint256 amountIn) external view returns (uint256);
11 | }
12 |
--------------------------------------------------------------------------------
/contracts/interfaces/IRecoverable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IStore.sol";
5 |
6 | interface IRecoverable {
7 | function s() external view returns (IStore);
8 |
9 | function recoverEther(address sendTo) external;
10 |
11 | function recoverToken(address token, address sendTo) external;
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/interfaces/IResolution.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IFinalization.sol";
5 | import "./IResolvable.sol";
6 | import "./IUnstakable.sol";
7 | import "./IMember.sol";
8 |
9 | //solhint-disable-next-line
10 | interface IResolution is IFinalization, IResolvable, IUnstakable, IMember {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/interfaces/IResolvable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IResolvable {
6 | event Resolved(
7 | bytes32 indexed coverKey,
8 | bytes32 indexed productKey,
9 | uint256 incidentDate,
10 | uint256 resolutionDeadline,
11 | bool decision,
12 | bool emergency,
13 | uint256 claimBeginsFrom,
14 | uint256 claimExpiresAt
15 | );
16 | event CooldownPeriodConfigured(bytes32 indexed coverKey, uint256 period);
17 | event ReportClosed(bytes32 indexed coverKey, bytes32 indexed productKey, address indexed closedBy, uint256 incidentDate);
18 |
19 | function resolve(
20 | bytes32 coverKey,
21 | bytes32 productKey,
22 | uint256 incidentDate
23 | ) external;
24 |
25 | function emergencyResolve(
26 | bytes32 coverKey,
27 | bytes32 productKey,
28 | uint256 incidentDate,
29 | bool decision
30 | ) external;
31 |
32 | function closeReport(
33 | bytes32 coverKey,
34 | bytes32 productKey,
35 | uint256 incidentDate
36 | ) external;
37 |
38 | function configureCoolDownPeriod(bytes32 coverKey, uint256 period) external;
39 |
40 | function getCoolDownPeriod(bytes32 coverKey) external view returns (uint256);
41 |
42 | function getResolutionDeadline(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/interfaces/IUnstakable.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IStore.sol";
5 |
6 | interface IUnstakable {
7 | struct UnstakeInfoType {
8 | uint256 totalStakeInWinningCamp;
9 | uint256 totalStakeInLosingCamp;
10 | uint256 myStakeInWinningCamp;
11 | uint256 toBurn;
12 | uint256 toReporter;
13 | uint256 myReward;
14 | uint256 unstaken;
15 | }
16 |
17 | event Unstaken(bytes32 indexed coverKey, bytes32 indexed productKey, address indexed caller, uint256 originalStake, uint256 reward);
18 | event ReporterRewardDistributed(bytes32 indexed coverKey, bytes32 indexed productKey, address caller, address indexed reporter, uint256 originalReward, uint256 reporterReward);
19 | event GovernanceBurned(bytes32 indexed coverKey, bytes32 indexed productKey, address caller, address indexed burner, uint256 originalReward, uint256 burnedAmount);
20 |
21 | function unstake(
22 | bytes32 coverKey,
23 | bytes32 productKey,
24 | uint256 incidentDate
25 | ) external;
26 |
27 | function unstakeWithClaim(
28 | bytes32 coverKey,
29 | bytes32 productKey,
30 | uint256 incidentDate
31 | ) external;
32 |
33 | function getUnstakeInfoFor(
34 | address account,
35 | bytes32 coverKey,
36 | bytes32 productKey,
37 | uint256 incidentDate
38 | ) external view returns (UnstakeInfoType memory);
39 | }
40 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVaultFactory.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "./IStore.sol";
5 | import "./IMember.sol";
6 |
7 | interface IVaultFactory is IMember {
8 | event VaultDeployed(address vault, bytes32 indexed coverKey, string name, string symbol);
9 |
10 | function deploy(
11 | bytes32 coverKey,
12 | string calldata name,
13 | string calldata symbol
14 | ) external returns (address);
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/interfaces/IWitness.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | interface IWitness {
6 | event Attested(bytes32 indexed coverKey, bytes32 indexed productKey, address witness, uint256 indexed incidentDate, uint256 stake);
7 | event Refuted(bytes32 indexed coverKey, bytes32 indexed productKey, address witness, uint256 indexed incidentDate, uint256 stake);
8 |
9 | function attest(
10 | bytes32 coverKey,
11 | bytes32 productKey,
12 | uint256 incidentDate,
13 | uint256 stake
14 | ) external;
15 |
16 | function refute(
17 | bytes32 coverKey,
18 | bytes32 productKey,
19 | uint256 incidentDate,
20 | uint256 stake
21 | ) external;
22 |
23 | function getStatus(bytes32 coverKey, bytes32 productKey) external view returns (uint256);
24 |
25 | function isCoverNormal(bytes32 coverKey) external view returns (bool);
26 |
27 | function getStakes(
28 | bytes32 coverKey,
29 | bytes32 productKey,
30 | uint256 incidentDate
31 | ) external view returns (uint256, uint256);
32 |
33 | function getStakesOf(
34 | bytes32 coverKey,
35 | bytes32 productKey,
36 | uint256 incidentDate,
37 | address account
38 | ) external view returns (uint256, uint256);
39 | }
40 |
--------------------------------------------------------------------------------
/contracts/libraries/VaultFactoryLibV1.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "../core/liquidity/Vault.sol";
6 |
7 | library VaultFactoryLibV1 {
8 | /**
9 | * @dev Gets the bytecode of the `Vault` contract
10 | * @param s Provide the store instance
11 | * @param coverKey Provide the cover key
12 | * @param stablecoin Specify the liquidity token for this Vault
13 | */
14 | function getByteCodeInternal(
15 | IStore s,
16 | bytes32 coverKey,
17 | string calldata tokenName,
18 | string calldata tokenSymbol,
19 | address stablecoin
20 | ) external pure returns (bytes memory bytecode, bytes32 salt) {
21 | salt = keccak256(abi.encodePacked(ProtoUtilV1.NS_CONTRACTS, ProtoUtilV1.CNS_COVER_VAULT, coverKey));
22 |
23 | //slither-disable-next-line too-many-digits
24 | bytecode = abi.encodePacked(type(Vault).creationCode, abi.encode(s, coverKey, tokenName, tokenSymbol, stablecoin));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/libraries/cxTokenFactoryLibV1.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 |
5 | import "../core/cxToken/cxToken.sol";
6 |
7 | // slither-disable-next-line naming-convention
8 | library cxTokenFactoryLibV1 {
9 | // solhint-disable-previous-line
10 | /**
11 | * @dev Gets the bytecode of the `cxToken` contract
12 | *
13 | * Warning: this function does not validate the input arguments.
14 | *
15 | * @param s Provide the store instance
16 | * @param coverKey Provide the cover key
17 | * @param expiryDate Specify the expiry date of this cxToken instance
18 | *
19 | */
20 | function getByteCodeInternal(
21 | IStore s,
22 | bytes32 coverKey,
23 | bytes32 productKey,
24 | string memory tokenName,
25 | uint256 expiryDate
26 | ) external pure returns (bytes memory bytecode, bytes32 salt) {
27 | salt = keccak256(abi.encodePacked(ProtoUtilV1.NS_COVER_CXTOKEN, coverKey, productKey, expiryDate));
28 |
29 | //slither-disable-next-line too-many-digits
30 | bytecode = abi.encodePacked(type(cxToken).creationCode, abi.encode(s, coverKey, productKey, tokenName, expiryDate));
31 | require(bytecode.length > 0, "Invalid bytecode");
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/mock/MockRegistryClient.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../libraries/RegistryLibV1.sol";
5 |
6 | contract MockRegistryClient {
7 | using RegistryLibV1 for IStore;
8 | IStore public s;
9 |
10 | constructor(IStore store) {
11 | s = store;
12 | }
13 |
14 | function getGovernanceContract() external view returns (IGovernance) {
15 | return s.getGovernanceContract();
16 | }
17 |
18 | function getPolicyContract() external view returns (IPolicy) {
19 | return s.getPolicyContract();
20 | }
21 |
22 | function getBondPoolContract() external view returns (IBondPool) {
23 | return s.getBondPoolContract();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/contracts/mock/base/MockCxToken.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
5 |
6 | contract MockCxToken is ERC20 {
7 | constructor() ERC20("Test", "Test") {
8 | super._mint(msg.sender, 1 ether);
9 | }
10 |
11 | function burn(uint256 amount) external {
12 | super._burn(msg.sender, amount);
13 | }
14 |
15 | function expiresOn() external view returns (uint256) {
16 | return block.timestamp + 30 days; // solhint-disable-line
17 | }
18 |
19 | function getClaimablePolicyOf(address) external pure returns (uint256) {
20 | return 1000 ether;
21 | }
22 |
23 | // slither-disable-next-line naming-convention
24 | function COVER_KEY() external pure returns (bytes32) {
25 | // solhint-disable-previous-line
26 | return "test";
27 | }
28 |
29 | // slither-disable-next-line naming-convention
30 | function PRODUCT_KEY() external pure returns (bytes32) {
31 | // solhint-disable-previous-line
32 | return "";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/contracts/mock/base/MockProtocol.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/access/AccessControl.sol";
5 |
6 | // slither-disable-next-line missing-inheritance
7 | contract MockProtocol is AccessControl {
8 | bool public state = false;
9 |
10 | function setPaused(bool s) external {
11 | state = s;
12 | }
13 |
14 | function paused() external view returns (bool) {
15 | return state;
16 | }
17 |
18 | function setupRole(
19 | bytes32 role,
20 | bytes32 adminRole,
21 | address account
22 | ) external {
23 | _setRoleAdmin(role, adminRole);
24 |
25 | if (account != address(0)) {
26 | _setupRole(role, account);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/contracts/mock/base/MockStore.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../fakes/FakeStore.sol";
5 |
6 | contract MockStore is FakeStore {
7 | function setBool(bytes32 prefix, address a) external {
8 | bytes32 k = keccak256(abi.encodePacked(prefix, a));
9 | this.setBool(k, true);
10 | }
11 |
12 | function unsetBool(bytes32 prefix, address a) external {
13 | bytes32 k = keccak256(abi.encodePacked(prefix, a));
14 | this.deleteBool(k);
15 | }
16 |
17 | function setAddress(
18 | bytes32 k1,
19 | bytes32 k2,
20 | address v
21 | ) public {
22 | this.setAddress(keccak256(abi.encodePacked(k1, k2)), v);
23 | }
24 |
25 | function setAddress(
26 | bytes32 k1,
27 | bytes32 k2,
28 | bytes32 k3,
29 | address v
30 | ) external {
31 | this.setAddress(keccak256(abi.encodePacked(k1, k2, k3)), v);
32 | }
33 |
34 | function setUint(
35 | bytes32 k1,
36 | bytes32 k2,
37 | uint256 v
38 | ) external {
39 | this.setUint(keccak256(abi.encodePacked(k1, k2)), v);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/contracts/mock/claims-processor/MockVault.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
5 |
6 | contract MockVault is ERC20 {
7 | constructor() ERC20("POD", "POD") {
8 | super._mint(msg.sender, 100_000 ether);
9 | }
10 |
11 | function transferGovernance(
12 | bytes32,
13 | address sender,
14 | uint256 amount
15 | ) external {
16 | if (sender != address(0)) {
17 | super._mint(sender, amount);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/mock/cx-token/MockCxTokenPolicy.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../interfaces/ICxToken.sol";
5 |
6 | contract MockCxTokenPolicy {
7 | ICxToken public cxToken;
8 |
9 | constructor(ICxToken _cxToken) {
10 | cxToken = _cxToken;
11 | }
12 |
13 | function callMint(
14 | bytes32 key,
15 | bytes32 productKey,
16 | address to,
17 | uint256 amount
18 | ) external {
19 | cxToken.mint(1, key, productKey, to, amount);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/contracts/mock/cx-token/MockCxTokenStore.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../base/MockStore.sol";
5 | import "../base/MockProtocol.sol";
6 | import "../../libraries/ProtoUtilV1.sol";
7 | import "../../fakes/FakePriceOracle.sol";
8 |
9 | contract MockCxTokenStore is MockStore {
10 | function initialize() external returns (address) {
11 | MockProtocol protocol = new MockProtocol();
12 | FakePriceOracle oracle = new FakePriceOracle();
13 |
14 | this.setAddress(ProtoUtilV1.CNS_CORE, address(protocol));
15 | this.setAddress(ProtoUtilV1.CNS_NPM_PRICE_ORACLE, address(oracle));
16 |
17 | return address(protocol);
18 | }
19 |
20 | function registerPolicyContract(address policy) external {
21 | super.setAddress(ProtoUtilV1.NS_CONTRACTS, ProtoUtilV1.CNS_COVER_POLICY, policy);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/contracts/mock/lib-user/MockAccessControlUser.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../libraries/AccessControlLibV1.sol";
5 | import "../../libraries/ProtoUtilV1.sol";
6 |
7 | contract MockAccessControlUser {
8 | using AccessControlLibV1 for IStore;
9 | using ProtoUtilV1 for IStore;
10 | using StoreKeyUtil for IStore;
11 |
12 | IStore public s;
13 |
14 | constructor(IStore store) {
15 | s = store;
16 | }
17 |
18 | function callerMustBeAdmin(address caller) external view {
19 | s.callerMustBeAdmin(caller);
20 | }
21 |
22 | function callerMustBeCoverManager(address caller) external view {
23 | s.callerMustBeCoverManager(caller);
24 | }
25 |
26 | function callerMustBeGovernanceAgent(address caller) external view {
27 | s.callerMustBeGovernanceAgent(caller);
28 | }
29 |
30 | function callerMustBeGovernanceAdmin(address caller) external view {
31 | s.callerMustBeGovernanceAdmin(caller);
32 | }
33 |
34 | function callerMustBeRecoveryAgent(address caller) external view {
35 | s.callerMustBeRecoveryAgent(caller);
36 | }
37 |
38 | function callerMustBePauseAgent(address caller) external view {
39 | s.callerMustBePauseAgent(caller);
40 | }
41 |
42 | function callerMustBeUnpauseAgent(address caller) external view {
43 | s.callerMustBeUnpauseAgent(caller);
44 | }
45 |
46 | function hasAccess(bytes32 role, address user) external view returns (bool) {
47 | return s.hasAccessInternal(role, user);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/contracts/mock/lib-user/MockCoverUtil.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../libraries/StoreKeyUtil.sol";
5 | import "../../libraries/ProtoUtilV1.sol";
6 | import "../../libraries/CoverUtilV1.sol";
7 | import "../../libraries/StrategyLibV1.sol";
8 |
9 | contract MockCoverUtilUser {
10 | using ProtoUtilV1 for IStore;
11 | using StoreKeyUtil for IStore;
12 | using StrategyLibV1 for IStore;
13 | using CoverUtilV1 for IStore;
14 |
15 | IStore public s;
16 |
17 | constructor(IStore store) {
18 | s = store;
19 | }
20 |
21 | function getActiveLiquidityUnderProtection(bytes32 coverKey, bytes32 productKey) external view returns (uint256) {
22 | uint256 precision = s.getStablecoinPrecisionInternal();
23 | return s.getActiveLiquidityUnderProtectionInternal(coverKey, productKey, precision);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/contracts/mock/lib-user/MockLiquidityEngineUser.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../libraries/StoreKeyUtil.sol";
5 | import "../../libraries/ProtoUtilV1.sol";
6 | import "../../libraries/CoverUtilV1.sol";
7 | import "../../libraries/StrategyLibV1.sol";
8 |
9 | contract MockLiquidityEngineUser {
10 | using ProtoUtilV1 for IStore;
11 | using StoreKeyUtil for IStore;
12 | using StrategyLibV1 for IStore;
13 | using CoverUtilV1 for IStore;
14 |
15 | IStore public s;
16 |
17 | constructor(IStore store) {
18 | s = store;
19 | }
20 |
21 | function setMaxLendingRatioInternal(uint256 ratio) external {
22 | s.setMaxLendingRatioInternal(ratio);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/contracts/mock/lib-user/MockValidationLibUser.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | pragma solidity ^0.8.0;
4 | import "../../libraries/ValidationLibV1.sol";
5 |
6 | contract MockValidationLibUser {
7 | using ValidationLibV1 for IStore;
8 | IStore public s;
9 |
10 | constructor(IStore store) {
11 | s = store;
12 | }
13 |
14 | function senderMustBePolicyManagerContract() external view {
15 | s.senderMustBePolicyManagerContract();
16 | }
17 |
18 | function senderMustBeGovernanceContract() external view {
19 | s.senderMustBeGovernanceContract();
20 | }
21 |
22 | function senderMustBeClaimsProcessorContract() external view {
23 | s.senderMustBeClaimsProcessorContract();
24 | }
25 |
26 | function senderMustBeStrategyContract() external view {
27 | s.senderMustBeStrategyContract();
28 | }
29 |
30 | function mustBeDisputed(bytes32 coverKey, bytes32 productKey) external view {
31 | s.mustBeDisputed(coverKey, productKey);
32 | }
33 |
34 | function mustHaveNormalProductStatus(bytes32 coverKey, bytes32 productKey) external view {
35 | s.mustHaveNormalProductStatus(coverKey, productKey);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/contracts/pool/Bond/BondPool.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 | import "./BondPoolBase.sol";
4 |
5 | contract BondPool is BondPoolBase {
6 | using BondPoolLibV1 for IStore;
7 | using ValidationLibV1 for IStore;
8 |
9 | constructor(IStore s) BondPoolBase(s) {} //solhint-disable-line
10 |
11 | /**
12 | * @dev Create a new bond contract by supplying your LP tokens
13 | *
14 | * @custom:suppress-acl This is a publicly accessible feature
15 | *
16 | */
17 | function createBond(uint256 lpTokens, uint256 minNpmDesired) external override nonReentrant {
18 | s.mustNotBePaused();
19 |
20 | require(lpTokens > 0, "Please specify `lpTokens`");
21 | require(minNpmDesired > 0, "Please enter `minNpmDesired`");
22 |
23 | (uint256 npmToVest, uint256 unlockDate) = s.createBondInternal(lpTokens, minNpmDesired);
24 | emit BondCreated(msg.sender, lpTokens, npmToVest, unlockDate);
25 | }
26 |
27 | /**
28 | * @dev Claim your bond and receive your NPM tokens after waiting period
29 | *
30 | * @custom:suppress-acl This is a publicly accessible feature
31 | *
32 | */
33 | function claimBond() external override nonReentrant {
34 | s.mustNotBePaused();
35 |
36 | // @suppress-zero-value-check The uint values are validated in the function `claimBondInternal`
37 | uint256 npmTransferred = s.claimBondInternal();
38 | emit BondClaimed(msg.sender, npmTransferred);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/contracts/pool/Staking/StakingPoolInfo.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 | import "./StakingPoolReward.sol";
4 |
5 | abstract contract StakingPoolInfo is StakingPoolReward {
6 | using StakingPoolLibV1 for IStore;
7 |
8 | constructor(IStore s) StakingPoolReward(s) {} //solhint-disable-line
9 |
10 | /**
11 | * @dev Gets the info of a given staking pool by key
12 | * @param key Provide the staking pool key to fetch info for
13 | * @param you Specify the address to customize the info for
14 | *
15 | */
16 | function getInfo(bytes32 key, address you) external view override returns (StakingPoolInfoType memory) {
17 | return s.getInfoInternal(key, you);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/pool/Staking/StakingPoolReward.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 | import "./StakingPoolBase.sol";
4 |
5 | abstract contract StakingPoolReward is StakingPoolBase {
6 | using ValidationLibV1 for IStore;
7 | using StakingPoolCoreLibV1 for IStore;
8 | using StakingPoolLibV1 for IStore;
9 |
10 | constructor(IStore s) StakingPoolBase(s) {} //solhint-disable-line
11 |
12 | function calculateRewards(bytes32 key, address account) external view override returns (uint256) {
13 | return s.calculateRewardsInternal(key, account);
14 | }
15 |
16 | /**
17 | * @dev Withdraw your staking reward. Ensure that you preiodically call this function
18 | * or else you risk receiving no rewards as a result of token depletion in the reward pool.
19 | *
20 | * @custom:suppress-acl This is a publicly accessible feature
21 | *
22 | */
23 | function withdrawRewards(bytes32 key) external override nonReentrant {
24 | s.mustNotBePaused();
25 | s.ensureValidStakingPoolInternal(key);
26 |
27 | (address rewardToken, uint256 rewards, uint256 platformFee) = s.withdrawRewardsInternal(key, msg.sender);
28 |
29 | if (rewards > 0) {
30 | emit RewardsWithdrawn(key, msg.sender, rewardToken, rewards, platformFee);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/dedicated/exchanges/index.js:
--------------------------------------------------------------------------------
1 | const binance = require('./binance')
2 | const coinbase = require('./coinbase')
3 | const huobi = require('./huobi')
4 | const okx = require('./okx')
5 |
6 | module.exports = [binance, coinbase, huobi, okx]
7 |
--------------------------------------------------------------------------------
/examples/dedicated/index.js:
--------------------------------------------------------------------------------
1 | const exchanges = require('./exchanges')
2 |
3 | module.exports = [...exchanges]
4 |
--------------------------------------------------------------------------------
/examples/diversified/animoca/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../util')
2 | const { ether, percentage, STABLECOIN_DECIMALS } = helper
3 |
4 | const MINUTES = 60
5 | const PRECISION = STABLECOIN_DECIMALS
6 |
7 | module.exports = {
8 | coverKey: key.toBytes32('animoca'),
9 | coverName: 'Animoca Brands',
10 | projectName: null,
11 | tokenName: 'Yield Bearing USDC',
12 | tokenSymbol: 'iUSDC-AB',
13 | requiresWhitelist: false,
14 | supportsProducts: true,
15 | leverageFactor: '5',
16 | tags: ['nft', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'payment'],
17 | about: '',
18 | blockchains: [{
19 | chainId: 1,
20 | name: 'Main Ethereum Network'
21 | }],
22 | floor: percentage(2),
23 | ceiling: percentage(15),
24 | reportingPeriod: 5 * MINUTES,
25 | cooldownPeriod: 5 * MINUTES,
26 | claimPeriod: 5 * MINUTES,
27 | minStakeToReport: ether(2000),
28 | stakeWithFee: ether(25000),
29 | initialReassuranceAmount: ether(50_000, PRECISION),
30 | reassuranceRate: percentage(25)
31 | }
32 |
--------------------------------------------------------------------------------
/examples/diversified/animoca/products/index.js:
--------------------------------------------------------------------------------
1 | module.exports = []
2 |
--------------------------------------------------------------------------------
/examples/diversified/defi/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../util')
2 | const { ether, percentage, STABLECOIN_DECIMALS } = helper
3 |
4 | const MINUTES = 60
5 | const PRECISION = STABLECOIN_DECIMALS
6 |
7 | module.exports = {
8 | coverKey: key.toBytes32('defi'),
9 | coverName: 'Popular DeFi Apps',
10 | projectName: null,
11 | tokenName: 'Yield Bearing USDC',
12 | tokenSymbol: 'iUSDC-POP',
13 | requiresWhitelist: false,
14 | supportsProducts: true,
15 | leverageFactor: '10',
16 | tags: ['nft', 'exchange', 'dex', 'swap', 'fork', 'stablecoin', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'insurance', 'payment'],
17 | about: '',
18 | blockchains: [{
19 | chainId: 1,
20 | name: 'Main Ethereum Network'
21 | }],
22 | floor: percentage(2),
23 | ceiling: percentage(12),
24 | reportingPeriod: 5 * MINUTES,
25 | cooldownPeriod: 5 * MINUTES,
26 | claimPeriod: 5 * MINUTES,
27 | minStakeToReport: ether(2000),
28 | stakeWithFee: ether(25000),
29 | initialReassuranceAmount: ether(50_000, PRECISION),
30 | reassuranceRate: percentage(25)
31 | }
32 |
--------------------------------------------------------------------------------
/examples/diversified/defi/index.js:
--------------------------------------------------------------------------------
1 | const cover = require('./cover')
2 | const products = require('./products')
3 |
4 | module.exports = { cover, products }
5 |
--------------------------------------------------------------------------------
/examples/diversified/defi/products/index.js:
--------------------------------------------------------------------------------
1 | const oneInch = require('./1inch')
2 | const compound = require('./compound')
3 | const convex = require('./convex')
4 | const kyberswap = require('./kyberswap')
5 | const lido = require('./lido')
6 | const nexusMutual = require('./nexus-mutual')
7 | const rocketPool = require('./rocket-pool')
8 | const sushi = require('./sushi')
9 | const uniswap = require('./uniswap')
10 |
11 | module.exports = [
12 | oneInch,
13 | compound,
14 | convex,
15 | kyberswap,
16 | lido,
17 | nexusMutual,
18 | rocketPool,
19 | sushi,
20 | uniswap
21 | ]
22 |
--------------------------------------------------------------------------------
/examples/diversified/index.js:
--------------------------------------------------------------------------------
1 | const defi = require('./defi')
2 | const prime = require('./prime')
3 |
4 | const covers = [
5 | defi.cover,
6 | prime.cover
7 | ]
8 |
9 | const products = [
10 | ...defi.products,
11 | ...prime.products
12 | ]
13 |
14 | module.exports = { covers, products }
15 |
--------------------------------------------------------------------------------
/examples/diversified/prime/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../util')
2 | const { ether, percentage, STABLECOIN_DECIMALS } = helper
3 |
4 | const MINUTES = 60
5 | const PRECISION = STABLECOIN_DECIMALS
6 |
7 | module.exports = {
8 | coverKey: key.toBytes32('prime'),
9 | coverName: 'Prime dApps',
10 | projectName: null,
11 | tokenName: 'Yield Bearing USDC',
12 | tokenSymbol: 'iUSDC-PRI',
13 | requiresWhitelist: false,
14 | supportsProducts: true,
15 | leverageFactor: '10',
16 | tags: ['nft', 'exchange', 'dex', 'swap', 'fork', 'stablecoin', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'insurance', 'payment'],
17 | about: '',
18 | blockchains: [{
19 | chainId: 1,
20 | name: 'Main Ethereum Network'
21 | }],
22 | floor: percentage(0.5),
23 | ceiling: percentage(8),
24 | reportingPeriod: 5 * MINUTES,
25 | cooldownPeriod: 5 * MINUTES,
26 | claimPeriod: 5 * MINUTES,
27 | minStakeToReport: ether(2000),
28 | stakeWithFee: ether(25000),
29 | initialReassuranceAmount: ether(50_000, PRECISION),
30 | reassuranceRate: percentage(25)
31 | }
32 |
--------------------------------------------------------------------------------
/examples/diversified/prime/index.js:
--------------------------------------------------------------------------------
1 | const cover = require('./cover')
2 | const products = require('./products')
3 |
4 | module.exports = { cover, products }
5 |
--------------------------------------------------------------------------------
/examples/diversified/prime/products/index.js:
--------------------------------------------------------------------------------
1 | const aave = require('./aave')
2 | const balancer = require('./balancer')
3 | const curve = require('./curve')
4 | const gnosisSafe = require('./gnosis-safe')
5 | const maker = require('./maker')
6 | const synthetix = require('./synthetix')
7 | const uniswap = require('./uniswap')
8 |
9 | module.exports = [aave, balancer, curve, gnosisSafe, maker, synthetix, uniswap]
10 |
--------------------------------------------------------------------------------
/examples/index.js:
--------------------------------------------------------------------------------
1 | const diversified = require('./diversified')
2 | const dedicated = require('./dedicated')
3 |
4 | const covers = [
5 | ...diversified.covers,
6 | ...dedicated
7 | ]
8 |
9 | const { products } = diversified
10 |
11 | module.exports = { covers, diversified, dedicated, products }
12 |
--------------------------------------------------------------------------------
/files/protocol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neptune-mutual-blue/protocol/1256dfc57bd727bdba171d34eabd4176db89f999/files/protocol.png
--------------------------------------------------------------------------------
/fuzzing/core/StoreTest.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 |
4 | pragma solidity ^0.8.0;
5 |
6 | import "forge-std/Test.sol";
7 | import "forge-std/Vm.sol";
8 | import "../../contracts/core/store/Store.sol";
9 |
10 | contract StoreTest is Test {
11 | Store public store;
12 | using stdStorage for StdStorage;
13 |
14 | function setUp() public {
15 | store = new Store();
16 | }
17 |
18 | function testSetUint(bytes32 key, uint256 value) public {
19 | store.setUint(key, value);
20 | assertEq(store.getUint(key), value);
21 | }
22 |
23 | function testSetUintAsNonMember(bytes32 key, uint256 value) public {
24 | vm.expectRevert("Forbidden");
25 | vm.prank(address(2));
26 | store.setUint(key, value);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/oracle/contracts/IPriceOracle.sol:
--------------------------------------------------------------------------------
1 | // Neptune Mutual Protocol (https://neptunemutual.com)
2 | // SPDX-License-Identifier: BUSL-1.1
3 | // solhint-disable compiler-version
4 | pragma solidity 0.6.6;
5 |
6 | interface IPriceOracle {
7 | event PriceUpdated(address indexed updater, uint32 timeElapsed, uint256 price0Cumulative, uint256 price1Cumulative);
8 |
9 | function update() external;
10 |
11 | function consult(address token, uint256 amountIn) external view returns (uint256);
12 |
13 | function consultPair(uint256 amountIn) external view returns (uint256);
14 | }
15 |
--------------------------------------------------------------------------------
/oracle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "npm-price-oracle",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "compile": "cp ../.env .env && hardhat compile",
8 | "build": "cp ../.env .env && hardhat compile",
9 | "clean": "hardhat clean",
10 | "compile:clean": "cp ../.env .env && hardhat clean && hardhat compile",
11 | "build:clean": "npm run compile:clean",
12 | "deploy": "hardhat run scripts/deploy.js --network hardhat",
13 | "deploy:mumbai": "hardhat run scripts/deploy.js --network mumbai",
14 | "deploy:fuji": "hardhat run scripts/deploy.js --network fuji",
15 | "slither": "slither .",
16 | "fix": "standard --fix"
17 | },
18 | "author": "",
19 | "license": "SEE LICENSE IN ",
20 | "bugs": {
21 | "url": "https://github.com/neptune-mutual/protocol/issues"
22 | },
23 | "homepage": "https://github.com/neptune-mutual/protocol#readme",
24 | "standard": {
25 | "env": [
26 | "mocha"
27 | ],
28 | "global": [
29 | "ethers",
30 | "task",
31 | "contract",
32 | "artifacts",
33 | "web3"
34 | ]
35 | },
36 | "devDependencies": {
37 | "@nomiclabs/hardhat-ethers": "^2.0.3",
38 | "@nomiclabs/hardhat-etherscan": "^3.1.7",
39 | "@nomiclabs/hardhat-waffle": "^2.0.1",
40 | "@uniswap/lib": "^4.0.1-alpha",
41 | "@uniswap/v2-core": "1.0.0",
42 | "@uniswap/v2-periphery": "^1.1.0-beta.0",
43 | "dotenv": "^10.0.0",
44 | "ethereum-waffle": "^3.4.0",
45 | "ethers": "^5.5.2",
46 | "hardhat": "2.19.3",
47 | "hardhat-contract-sizer": "2.1.1",
48 | "hardhat-gas-reporter": "1.0.6",
49 | "openzeppelin-solidity": "3.4.0",
50 | "solidity-coverage": "^0.8.7",
51 | "standard": "^16.0.4"
52 | },
53 | "volta": {
54 | "node": "18.12.0",
55 | "yarn": "1.22.19"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/oracle/scripts/deploy.js:
--------------------------------------------------------------------------------
1 | const { network } = require('hardhat')
2 | const { ethers } = require('hardhat')
3 | const config = require('../../scripts/config/network')
4 |
5 | const main = async () => {
6 | const [deployer] = await ethers.getSigners()
7 | const chainId = network.config.chainId
8 |
9 | console.log('Deployer: %s. Balance: %s', deployer.address, await deployer.getBalance())
10 |
11 | const ContractFactory = await ethers.getContractFactory('NpmPriceOracle')
12 |
13 | const oracle = await ContractFactory.deploy(config[chainId].stablecoinPairs.NPM_STABLECOIN, config[chainId].deployedTokens.NPM)
14 | await oracle.deployed()
15 |
16 | console.log('Deployed: %s/address/%s', network.config.explorer, oracle.address)
17 | }
18 |
19 | main()
20 | .then(() => process.exit(0))
21 | .catch((error) => {
22 | console.error(error)
23 | process.exit(1)
24 | })
25 |
--------------------------------------------------------------------------------
/remappings.txt:
--------------------------------------------------------------------------------
1 | ds-test/=lib/forge-std/lib/ds-test/src/
2 | forge-std/=lib/forge-std/src/
3 | @ensdomains/=node_modules/@ensdomains/
4 | eth-gas-reporter/=node_modules/eth-gas-reporter/
5 | hardhat/=node_modules/hardhat/
6 | openzeppelin-solidity/=node_modules/openzeppelin-solidity/
7 |
--------------------------------------------------------------------------------
/scripts/config/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {}
2 |
--------------------------------------------------------------------------------
/scripts/config/network/hardhat.js:
--------------------------------------------------------------------------------
1 | const { ACCESS_CONTROL } = require('../../../util/key')
2 | const wallet = require('../../../util/wallet')
3 |
4 | const DAYS = 86400
5 | const HOURS = 3600
6 |
7 | const config = {
8 | 31338: {
9 | network: 'Hardhat',
10 | name: 'hardhat',
11 | chainId: 31338,
12 | mainnet: false,
13 | pool: {
14 | bond: {
15 | period: 7 * DAYS
16 | }
17 | },
18 | cover: {
19 | lendingPeriod: 180 * DAYS,
20 | withdrawalWindow: 7 * DAYS,
21 | claimPeriod: 7 * DAYS,
22 | cooldownPeriod: 1 * DAYS,
23 | reportingPeriod: 7 * DAYS,
24 | stateUpdateInterval: 1 * HOURS
25 | },
26 | // knownAccounts,
27 | // uniswapV2Like,
28 | knownAccounts: [
29 | {
30 | account: '0xA96813969437F3bad7B59335934aa75933670615',
31 | roles: [
32 | ACCESS_CONTROL.ADMIN,
33 | ACCESS_CONTROL.COVER_MANAGER,
34 | ACCESS_CONTROL.LIQUIDITY_MANAGER,
35 | ACCESS_CONTROL.GOVERNANCE_ADMIN,
36 | ACCESS_CONTROL.RECOVERY_AGENT,
37 | ACCESS_CONTROL.UNPAUSE_AGENT,
38 | ACCESS_CONTROL.UPGRADE_AGENT
39 | ]
40 | }, {
41 | account: wallet.toWalletAddress(process.env.PRIVATE_KEY),
42 | roles: [
43 | ACCESS_CONTROL.ADMIN,
44 | ACCESS_CONTROL.COVER_MANAGER,
45 | ACCESS_CONTROL.LIQUIDITY_MANAGER,
46 | ACCESS_CONTROL.GOVERNANCE_ADMIN,
47 | ACCESS_CONTROL.RECOVERY_AGENT,
48 | ACCESS_CONTROL.UNPAUSE_AGENT,
49 | ACCESS_CONTROL.UPGRADE_AGENT
50 | ]
51 | }
52 | ],
53 | uniswapV2Like: null,
54 | protocol: {
55 | burner: '0x0000000000000000000000000000000000000001',
56 | treasury: '0x0000000000000000000000000000000000000001'
57 | }
58 | }
59 | }
60 |
61 | module.exports = config
62 |
--------------------------------------------------------------------------------
/scripts/config/network/index.js:
--------------------------------------------------------------------------------
1 | const hardhat = require('./hardhat')
2 | const mainnet = require('./mainnet')
3 | const arbitrum = require('./arbitrum')
4 | const bsc = require('./bsc')
5 | const baseGoerli = require('./base-goerli')
6 | const local = require('./local')
7 |
8 | module.exports = {
9 | ...hardhat,
10 | ...baseGoerli,
11 | ...mainnet,
12 | ...arbitrum,
13 | ...bsc,
14 | ...local
15 | }
16 |
--------------------------------------------------------------------------------
/scripts/config/network/local.js:
--------------------------------------------------------------------------------
1 | const mainnet = require('./bsc')
2 |
3 | const config = {}
4 | config[31337] = { ...mainnet[56] }
5 | config[31337].network = 'Hardhat Forked BNB Chain Network'
6 | config[31337].mainnet = true
7 | config[31337].chainId = 31337
8 |
9 | module.exports = config
10 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps-bnb/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../../util')
2 | const { ether, percentage } = helper
3 |
4 | const DAYS = 86400
5 |
6 | module.exports = {
7 | coverKey: key.toBytes32('popular-defi-apps'),
8 | coverName: 'Popular DeFi Apps',
9 | projectName: null,
10 | tokenName: 'Yield Bearing USDC',
11 | tokenSymbol: 'iUSDC-POP',
12 | requiresWhitelist: false,
13 | supportsProducts: true,
14 | leverageFactor: '6',
15 | tags: ['nft', 'exchange', 'dex', 'swap', 'fork', 'stablecoin', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'insurance', 'payment'],
16 | about: '',
17 | blockchains: [
18 | {
19 | chainId: 56,
20 | name: 'BNB Chain'
21 | }
22 | ],
23 | floor: percentage(2),
24 | ceiling: percentage(12),
25 | reportingPeriod: 7 * DAYS,
26 | cooldownPeriod: 1 * DAYS,
27 | claimPeriod: 7 * DAYS,
28 | minStakeToReport: ether(10_000),
29 | stakeWithFee: ether(12_500),
30 | initialReassuranceAmount: '0',
31 | reassuranceRate: percentage(25)
32 | }
33 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps-bnb/index.js:
--------------------------------------------------------------------------------
1 | const cover = require('./cover')
2 | const products = require('./products')
3 |
4 | module.exports = { cover, products }
5 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps-bnb/products/index.js:
--------------------------------------------------------------------------------
1 | const alpaca = require('./alpaca')
2 | const dodo = require('./dodo')
3 | const oneInch = require('./one-inch')
4 | const pancakeswap = require('./pancakeswap')
5 | const uniswap = require('./uniswap')
6 |
7 | module.exports = [alpaca, dodo, oneInch, pancakeswap, uniswap]
8 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../../util')
2 | const { ether, percentage } = helper
3 |
4 | const DAYS = 86400
5 |
6 | module.exports = {
7 | coverKey: key.toBytes32('popular-defi-apps'),
8 | coverName: 'Popular DeFi Apps',
9 | projectName: null,
10 | tokenName: 'Yield Bearing USDC',
11 | tokenSymbol: 'iUSDC-POP',
12 | requiresWhitelist: false,
13 | supportsProducts: true,
14 | leverageFactor: '6',
15 | tags: ['nft', 'exchange', 'dex', 'swap', 'fork', 'stablecoin', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'insurance', 'payment'],
16 | about: '',
17 | blockchains: [{
18 | chainId: 1,
19 | name: 'Main Ethereum Network'
20 | },
21 | {
22 | chainId: 42161,
23 | name: 'Arbitrum'
24 | }],
25 | floor: percentage(2),
26 | ceiling: percentage(12),
27 | reportingPeriod: 7 * DAYS,
28 | cooldownPeriod: 1 * DAYS,
29 | claimPeriod: 7 * DAYS,
30 | minStakeToReport: ether(10_000),
31 | stakeWithFee: ether(30_000),
32 | initialReassuranceAmount: '0',
33 | reassuranceRate: percentage(25)
34 | }
35 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps/index.js:
--------------------------------------------------------------------------------
1 | const cover = require('./cover')
2 | const products = require('./products')
3 |
4 | module.exports = { cover, products }
5 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/popular-defi-apps/products/index.js:
--------------------------------------------------------------------------------
1 | const aave = require('./aave')
2 | const bancor = require('./bancor')
3 | const compound = require('./compound')
4 | const convex = require('./convex')
5 | const dydx = require('./dydx')
6 | const gmx = require('./gmx')
7 | const oneInch = require('./one-inch')
8 | const sushi = require('./sushi')
9 | const uniswap = require('./uniswap')
10 |
11 | module.exports = [aave, bancor, compound, convex, dydx, gmx, oneInch, sushi, uniswap]
12 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/prime/cover.js:
--------------------------------------------------------------------------------
1 | const { key, helper } = require('../../../../util')
2 | const { ether, percentage } = helper
3 |
4 | const DAYS = 86400
5 |
6 | module.exports = {
7 | coverKey: key.toBytes32('prime'),
8 | coverName: 'Prime dApps',
9 | projectName: null,
10 | tokenName: 'Yield Bearing USDC',
11 | tokenSymbol: 'iUSDC-PRI',
12 | requiresWhitelist: false,
13 | supportsProducts: true,
14 | leverageFactor: '6',
15 | tags: ['nft', 'exchange', 'dex', 'swap', 'fork', 'stablecoin', 'lending', 'flashloan', 'borrowing', 'interest', 'loan', 'staking', 'yield', 'insurance', 'payment'],
16 | about: '',
17 | blockchains: [{
18 | chainId: 1,
19 | name: 'Main Ethereum Network'
20 | }],
21 | floor: percentage(0.5),
22 | ceiling: percentage(8),
23 | reportingPeriod: 7 * DAYS,
24 | cooldownPeriod: 1 * DAYS,
25 | claimPeriod: 7 * DAYS,
26 | minStakeToReport: ether(10_000),
27 | stakeWithFee: ether(30_000),
28 | initialReassuranceAmount: '0',
29 | reassuranceRate: percentage(25)
30 | }
31 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/prime/index.js:
--------------------------------------------------------------------------------
1 | const cover = require('./cover')
2 | const products = require('./products')
3 |
4 | module.exports = { cover, products }
5 |
--------------------------------------------------------------------------------
/scripts/covers/diversified/prime/products/index.js:
--------------------------------------------------------------------------------
1 | const aave = require('./aave')
2 | const balancer = require('./balancer')
3 | const curve = require('./curve')
4 | const gnosisSafe = require('./gnosis-safe')
5 | const maker = require('./maker')
6 | const synthetix = require('./synthetix')
7 | const uniswap = require('./uniswap')
8 |
9 | module.exports = [aave, balancer, curve, gnosisSafe, maker, synthetix, uniswap]
10 |
--------------------------------------------------------------------------------
/scripts/deploy-covers.js:
--------------------------------------------------------------------------------
1 | const { deploy } = require('./covers/deployments/popular-defi-apps-bnb')
2 |
3 | deploy()
4 | .then(() => process.exit(0))
5 | .catch(error => {
6 | console.error(error)
7 | process.exit(1)
8 | })
9 |
--------------------------------------------------------------------------------
/scripts/deploy-npm.js:
--------------------------------------------------------------------------------
1 | const { formatEther } = require('ethers/lib/utils')
2 | const { network } = require('hardhat')
3 | const { ethers } = require('hardhat')
4 |
5 | const deploy = async (contractName, ...args) => {
6 | const ContractFactory = await ethers.getContractFactory(contractName)
7 | const instance = await ContractFactory.deploy(...args)
8 | await instance.deployed()
9 |
10 | const { explorer } = network.config
11 |
12 | if (explorer) {
13 | console.log('%s Deployed: %s/address/%s', contractName, network.config.explorer, instance.address)
14 | } else {
15 | console.log('%s Deployed: %s', contractName, instance.address)
16 | }
17 |
18 | return instance
19 | }
20 |
21 | const main = async () => {
22 | const [deployer] = await ethers.getSigners()
23 |
24 | const previousBalance = await deployer.getBalance()
25 |
26 | console.log('Deployer: %s. Balance: %s ETH', deployer.address, formatEther(previousBalance))
27 |
28 | await deploy('NPM', '0xAc6CD41F7E434DCf2Da45bb3ff385706DC2A2b9C', 'Neptune Mutual', 'NPM')
29 |
30 | const balance = await deployer.getBalance()
31 | const cost = previousBalance.sub(balance)
32 | console.log('Cost: %s ETH. Balance: %s ETH', formatEther(cost), formatEther(balance))
33 | }
34 |
35 | main()
36 | .then(() => process.exit(0))
37 | .catch((error) => {
38 | console.error(error)
39 | process.exit(1)
40 | })
41 |
--------------------------------------------------------------------------------
/scripts/deploy-pot.js:
--------------------------------------------------------------------------------
1 | const { formatEther } = require('ethers/lib/utils')
2 | const { network } = require('hardhat')
3 | const { ethers } = require('hardhat')
4 |
5 | const deploy = async (contractName, ...args) => {
6 | const ContractFactory = await ethers.getContractFactory(contractName)
7 | const instance = await ContractFactory.deploy(...args)
8 | await instance.deployed()
9 |
10 | const { explorer } = network.config
11 |
12 | if (explorer) {
13 | console.log('%s Deployed: %s/address/%s', contractName, network.config.explorer, instance.address)
14 | } else {
15 | console.log('%s Deployed: %s', contractName, instance.address)
16 | }
17 |
18 | return instance
19 | }
20 |
21 | const main = async () => {
22 | const [deployer] = await ethers.getSigners()
23 |
24 | const previousBalance = await deployer.getBalance()
25 |
26 | console.log('Deployer: %s. Balance: %s ETH', deployer.address, formatEther(previousBalance))
27 |
28 | await deploy('POT', deployer.address)
29 |
30 | const balance = await deployer.getBalance()
31 | const cost = previousBalance.sub(balance)
32 | console.log('Cost: %s ETH. Balance: %s ETH', formatEther(cost), formatEther(balance))
33 | }
34 |
35 | main()
36 | .then(() => process.exit(0))
37 | .catch((error) => {
38 | console.error(error)
39 | process.exit(1)
40 | })
41 |
--------------------------------------------------------------------------------
/scripts/deploy-treasury.js:
--------------------------------------------------------------------------------
1 | const { formatEther } = require('ethers/lib/utils')
2 | const { network } = require('hardhat')
3 | const { ethers } = require('hardhat')
4 |
5 | const OWNER = '0xAc6CD41F7E434DCf2Da45bb3ff385706DC2A2b9C'
6 |
7 | const deploy = async (contractName, ...args) => {
8 | const ContractFactory = await ethers.getContractFactory(contractName)
9 | const instance = await ContractFactory.deploy(...args)
10 | await instance.deployed()
11 |
12 | const { explorer } = network.config
13 |
14 | if (explorer) {
15 | console.log('%s Deployed: %s/address/%s', contractName, network.config.explorer, instance.address)
16 | } else {
17 | console.log('%s Deployed: %s', contractName, instance.address)
18 | }
19 |
20 | return instance
21 | }
22 |
23 | const main = async () => {
24 | const [deployer] = await ethers.getSigners()
25 |
26 | const previousBalance = await deployer.getBalance()
27 |
28 | console.log('Deployer: %s. Balance: %s ETH', deployer.address, formatEther(previousBalance))
29 |
30 | await deploy('Treasury', OWNER)
31 |
32 | const balance = await deployer.getBalance()
33 | const cost = previousBalance.sub(balance)
34 | console.log('Cost: %s ETH. Balance: %s ETH', formatEther(cost), formatEther(balance))
35 | }
36 |
37 | main()
38 | .then(() => process.exit(0))
39 | .catch((error) => {
40 | console.error(error)
41 | process.exit(1)
42 | })
43 |
--------------------------------------------------------------------------------
/slither.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "compile_force_framework": false,
3 | "hardhat_ignore_compile": false,
4 | "detectors_to_exclude": "assembly-usage,boolean-equality,solc-version,similar-names",
5 | "exclude_informational": false,
6 | "exclude_low": true,
7 | "exclude_medium": true,
8 | "exclude_high": false,
9 | "disable_color": false,
10 | "legacy_ast": false,
11 | "filter_paths": "./contracts/fakes|BokkyPooBahsDateTimeLibrary.sol|openzeppelin|Migrations.sol|lib"
12 | }
--------------------------------------------------------------------------------
/solidoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "pathToRoot": "./",
3 | "outputPath": "./docs",
4 | "noCompilation": true,
5 | "compiler": "truffle compile",
6 | "language": "en",
7 | "rootContract": "Cover",
8 | "readMe": "./readme.md"
9 | }
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.projectKey=neptune-mutual_protocol
2 | sonar.projectName=Neptune Mutual Protocol
3 | sonar.sources=.
4 | sonar.sourceEncoding=UTF-8
5 | #sonar.cpd.exclusions=
6 | sonar.exclusions=stories/**/*.js,test/**/*.js
7 | sonar.test.exclusions=stories/**/*.js,test/**/*.js
8 |
--------------------------------------------------------------------------------
/test/examples/distributor/drain.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, helper, key } = require('../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 | const PRECISION = helper.STABLECOIN_DECIMALS
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Distributor: `drain` function', () => {
14 | let deployed, treasury, feePercentage, distributor
15 |
16 | before(async () => {
17 | deployed = await deployDependencies()
18 |
19 | treasury = helper.randomAddress()
20 | feePercentage = helper.percentage(20)
21 |
22 | distributor = await deployer.deploy(cache, 'NpmDistributor', deployed.store.address, treasury, feePercentage)
23 | })
24 |
25 | it('must correctly drain the entire token balance', async () => {
26 | const coverKey = deployed.coverKey
27 | const amount = helper.ether(5000, PRECISION)
28 | const npmStakeToAdd = helper.ether(1000)
29 | const referralCode = key.toBytes32('referral-code')
30 |
31 | await deployed.npm.approve(distributor.address, npmStakeToAdd)
32 | await deployed.stablecoin.approve(distributor.address, amount)
33 |
34 | await deployed.npm.transfer(distributor.address, helper.ether(3333))
35 |
36 | const tx = await distributor.addLiquidity({
37 | coverKey,
38 | amount,
39 | npmStakeToAdd,
40 | referralCode
41 | })
42 |
43 | const { events } = await tx.wait()
44 | const event = events.find(x => x.event === 'Drained')
45 |
46 | event.args.token.should.equal(deployed.npm.address)
47 | event.args.to.should.equal(treasury)
48 | event.args.amount.should.equal(helper.ether(3333))
49 | })
50 | })
51 |
--------------------------------------------------------------------------------
/test/specs/claims-processor/deps.js:
--------------------------------------------------------------------------------
1 | const composer = require('../../../util/composer')
2 | const cache = null
3 |
4 | /**
5 | * Deploys all libraries
6 | * @return {Promise<{dependencies: Object, all: Libraries}>}
7 | */
8 | const deployDependencies = async () => {
9 | const all = await composer.libs.deployAll(cache)
10 |
11 | return {
12 | dependencies: {
13 | AccessControlLibV1: all.accessControlLibV1.address,
14 | BaseLibV1: all.baseLibV1.address,
15 | CoverUtilV1: all.coverUtilV1.address,
16 | GovernanceUtilV1: all.governanceUtilV1.address,
17 | RoutineInvokerLibV1: all.routineInvokerLibV1.address,
18 | NTransferUtilV2: all.transferLib.address,
19 | ProtoUtilV1: all.protoUtilV1.address,
20 | RegistryLibV1: all.registryLibV1.address,
21 | StoreKeyUtil: all.storeKeyUtil.address,
22 | ValidationLibV1: all.validationLibV1.address
23 | },
24 | all
25 | }
26 | }
27 |
28 | module.exports = { deployDependencies }
29 |
--------------------------------------------------------------------------------
/test/specs/cx-token-factory/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('cxTokenFactory: Constructor and Views', () => {
13 | let store, deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 |
18 | store = deployed.store
19 | })
20 |
21 | it('correctly deploys', async () => {
22 | const factory = await deployer.deployWithLibraries(cache, 'cxTokenFactory', {
23 | AccessControlLibV1: deployed.accessControlLibV1.address,
24 | BaseLibV1: deployed.baseLibV1.address,
25 | StoreKeyUtil: deployed.storeKeyUtil.address,
26 | ValidationLibV1: deployed.validationLibV1.address,
27 | cxTokenFactoryLibV1: deployed.cxTokenFactoryLib.address
28 | }, store.address)
29 |
30 | const _store = await factory.s()
31 | _store.should.equal(store.address)
32 |
33 | const version = await factory.version()
34 | version.should.equal(key.toBytes32('v0.1'))
35 |
36 | const name = await factory.getName()
37 | name.should.equal(key.PROTOCOL.CNAME.CXTOKEN_FACTORY)
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/test/specs/governance/resolution/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Resolution Constructor', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly deploys', async () => {
20 | const resolution = await deployer.deployWithLibraries(cache, 'Resolution',
21 | {
22 | AccessControlLibV1: deployed.accessControlLibV1.address,
23 | BaseLibV1: deployed.baseLibV1.address,
24 | RoutineInvokerLibV1: deployed.routineInvokerLibV1.address,
25 | StoreKeyUtil: deployed.storeKeyUtil.address,
26 | ProtoUtilV1: deployed.protoUtilV1.address,
27 | CoverUtilV1: deployed.coverUtilV1.address,
28 | NTransferUtilV2: deployed.transferLib.address,
29 | ValidationLibV1: deployed.validationLibV1.address,
30 | GovernanceUtilV1: deployed.governanceUtilV1.address
31 | },
32 | deployed.store.address
33 | )
34 |
35 | const version = await resolution.version()
36 | const name = await resolution.getName()
37 |
38 | version.should.equal(key.toBytes32('v0.1'))
39 | name.should.equal(key.PROTOCOL.CNAME.RESOLUTION)
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/test/specs/governance/set-reporter-burn-rate.spec.js:
--------------------------------------------------------------------------------
1 | const BigNumber = require('bignumber.js')
2 | const { deployDependencies } = require('./deps')
3 |
4 | require('chai')
5 | .use(require('chai-as-promised'))
6 | .use(require('chai-bignumber')(BigNumber))
7 | .should()
8 |
9 | describe('Governance: `setReportingBurnRate` function', () => {
10 | const burnRate = '1'
11 | let deployed
12 |
13 | before(async () => {
14 | deployed = await deployDependencies()
15 | })
16 |
17 | it('must correctly set reporter commission', async () => {
18 | const tx = await deployed.governance.setReportingBurnRate(burnRate)
19 | const { events } = await tx.wait()
20 | const event = events.find(x => x.event === 'ReportingBurnRateSet')
21 |
22 | event.args.current.should.equal(burnRate)
23 | })
24 |
25 | it('reverts when protocol is paused', async () => {
26 | await deployed.protocol.pause()
27 | await deployed.governance.setReportingBurnRate(burnRate).should.be.rejectedWith('Protocol is paused')
28 | await deployed.protocol.unpause()
29 | })
30 |
31 | it('reverts when zero is specified as burn rate', async () => {
32 | await deployed.governance.setReportingBurnRate('0').should.be.rejectedWith('Please specify value')
33 | })
34 |
35 | it('reverts when not accessed by CoverManager', async () => {
36 | const [, bob] = await ethers.getSigners()
37 |
38 | await deployed.governance.connect(bob).setReportingBurnRate(burnRate).should.be.rejectedWith('Forbidden')
39 | })
40 | })
41 |
--------------------------------------------------------------------------------
/test/specs/governance/set-reporter-commission.spec.js:
--------------------------------------------------------------------------------
1 | const BigNumber = require('bignumber.js')
2 | const { deployDependencies } = require('./deps')
3 |
4 | require('chai')
5 | .use(require('chai-as-promised'))
6 | .use(require('chai-bignumber')(BigNumber))
7 | .should()
8 |
9 | describe('Governance: `setReporterCommission` function', () => {
10 | const commission = '1'
11 | let deployed
12 |
13 | before(async () => {
14 | deployed = await deployDependencies()
15 | })
16 |
17 | it('must correctly set reporter commission', async () => {
18 | await deployed.governance.setReporterCommission(commission)
19 | })
20 |
21 | it('reverts when not accessed by CoverManager', async () => {
22 | const [, bob] = await ethers.getSigners()
23 |
24 | await deployed.governance.connect(bob).setReporterCommission(commission).should.be.rejectedWith('Forbidden')
25 | })
26 |
27 | it('reverts when protocol is paused', async () => {
28 | await deployed.protocol.pause()
29 | await deployed.governance.setReporterCommission(commission).should.be.rejectedWith('Protocol is paused')
30 | await deployed.protocol.unpause()
31 | })
32 |
33 | it('reverts when zero is specified as commision', async () => {
34 | await deployed.governance.setReporterCommission('0').should.be.rejectedWith('Please specify value')
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/test/specs/lifecycle/cover/set-cover-creation-fee.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployDependencies } = require('./deps')
4 |
5 | require('chai')
6 | .use(require('chai-as-promised'))
7 | .use(require('chai-bignumber')(BigNumber))
8 | .should()
9 |
10 | describe('Cover: setCoverCreationFee', () => {
11 | let deployed
12 |
13 | beforeEach(async () => {
14 | deployed = await deployDependencies()
15 | })
16 |
17 | it('correctly sets cover fees', async () => {
18 | const fees = '1'
19 |
20 | const tx = await deployed.cover.setCoverCreationFee(fees)
21 | const { events } = await tx.wait()
22 |
23 | const event = events.find(x => x.event === 'CoverCreationFeeSet')
24 | event.args.previous.should.equal('0')
25 | event.args.current.should.equal(fees)
26 | })
27 |
28 | it('reverts when invalid value is passed as cover fees', async () => {
29 | const fees = '0'
30 |
31 | await deployed.cover.setCoverCreationFee(fees)
32 | .should.be.rejectedWith('Please specify value')
33 | })
34 |
35 | it('reverts when protocol is paused', async () => {
36 | const fees = '1'
37 |
38 | await deployed.protocol.pause()
39 | await deployed.cover.setCoverCreationFee(fees)
40 | .should.be.rejectedWith('Protocol is paused')
41 | await deployed.protocol.unpause()
42 | })
43 |
44 | it('reverts when not accessed by cover manager', async () => {
45 | const [, bob] = await ethers.getSigners()
46 | const fees = '1'
47 |
48 | await deployed.cover.connect(bob).setCoverCreationFee(fees)
49 | .should.be.rejectedWith('Forbidden')
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/test/specs/lifecycle/cover/set-min-cover-creation-stake.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Cover: setMinCoverCreationStake', () => {
12 | let deployed
13 |
14 | beforeEach(async () => {
15 | deployed = await deployDependencies()
16 | })
17 |
18 | it('correctly sets min cover creation stake', async () => {
19 | const minStake = '1'
20 |
21 | const tx = await deployed.cover.setMinCoverCreationStake(minStake)
22 | const { events } = await tx.wait()
23 |
24 | const event = events.find(x => x.event === 'MinCoverCreationStakeSet')
25 | event.args.previous.should.equal(helper.ether(2))
26 | event.args.current.should.equal(minStake)
27 | })
28 |
29 | it('reverts when invalid value is passed as min stake', async () => {
30 | const minStake = '0'
31 |
32 | await deployed.cover.setMinCoverCreationStake(minStake)
33 | .should.be.rejectedWith('Please specify value')
34 | })
35 |
36 | it('reverts when protocol is paused', async () => {
37 | const minStake = '1'
38 |
39 | await deployed.protocol.pause()
40 | await deployed.cover.setMinCoverCreationStake(minStake)
41 | .should.be.rejectedWith('Protocol is paused')
42 | await deployed.protocol.unpause()
43 | })
44 |
45 | it('reverts when not accessed by cover manager', async () => {
46 | const [, bob] = await ethers.getSigners()
47 | const minStake = '1'
48 |
49 | await deployed.cover.connect(bob).setMinCoverCreationStake(minStake)
50 | .should.be.rejectedWith('Forbidden')
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/test/specs/lifecycle/cover/set-min-stake-to-add-liquidity.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Cover: setMinStakeToAddLiquidity', () => {
12 | let deployed
13 |
14 | beforeEach(async () => {
15 | deployed = await deployDependencies()
16 | })
17 |
18 | it('correctly sets min stake to add liquidity', async () => {
19 | const minStake = '1'
20 |
21 | const tx = await deployed.cover.setMinStakeToAddLiquidity(minStake)
22 | const { events } = await tx.wait()
23 |
24 | const event = events.find(x => x.event === 'MinStakeToAddLiquiditySet')
25 | event.args.previous.should.equal(helper.ether(0))
26 | event.args.current.should.equal(minStake)
27 | })
28 |
29 | it('reverts when protocol is paused', async () => {
30 | const minStake = '1'
31 |
32 | await deployed.protocol.pause()
33 | await deployed.cover.setMinStakeToAddLiquidity(minStake)
34 | .should.be.rejectedWith('Protocol is paused')
35 | await deployed.protocol.unpause()
36 | })
37 |
38 | it('reverts when not accessed by cover manager', async () => {
39 | const [, bob] = await ethers.getSigners()
40 | const minStake = '1'
41 |
42 | await deployed.cover.connect(bob).setMinStakeToAddLiquidity(minStake)
43 | .should.be.rejectedWith('Forbidden')
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/test/specs/lifecycle/cover/update-cover-creator-whitelist.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const { ethers } = require('hardhat')
3 | const BigNumber = require('bignumber.js')
4 | const { deployDependencies } = require('./deps')
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Cover: updateCoverCreatorWhitelist', () => {
12 | let deployed
13 |
14 | before(async () => {
15 | deployed = await deployDependencies()
16 | })
17 |
18 | it('correctly whitelists cover creator', async () => {
19 | const [owner, bob] = await ethers.getSigners()
20 |
21 | await deployed.cover.updateCoverCreatorWhitelist([owner.address], [true])
22 |
23 | const isWhitelistedOwner = await deployed.cover.checkIfWhitelistedCoverCreator(owner.address)
24 | isWhitelistedOwner.should.equal(true)
25 |
26 | const isWhitelistedBob = await deployed.cover.checkIfWhitelistedCoverCreator(bob.address)
27 | isWhitelistedBob.should.equal(false)
28 | })
29 |
30 | it('reverts when protocol is paused', async () => {
31 | await deployed.protocol.pause()
32 |
33 | const [owner] = await ethers.getSigners()
34 | await deployed.cover.updateCoverCreatorWhitelist([owner.address], [true])
35 | .should.be.rejectedWith('Protocol is paused')
36 |
37 | await deployed.protocol.unpause()
38 | })
39 |
40 | it('reverts when not accessed by CoverManager', async () => {
41 | const [owner, bob] = await ethers.getSigners()
42 |
43 | await deployed.cover.connect(bob).updateCoverCreatorWhitelist([owner.address], [true])
44 | .should.be.rejectedWith('Forbidden')
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/specs/liquidity/delegates/ctor-vfns.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('VaultDelegate Constructor and Views', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly deploys', async () => {
20 | const vaultDelegate = await deployer.deployWithLibraries(cache, 'VaultDelegate',
21 | {
22 | AccessControlLibV1: deployed.accessControlLibV1.address,
23 | BaseLibV1: deployed.baseLibV1.address,
24 | GovernanceUtilV1: deployed.governanceUtilV1.address,
25 | ProtoUtilV1: deployed.protoUtilV1.address,
26 | RoutineInvokerLibV1: deployed.routineInvokerLibV1.address,
27 | StoreKeyUtil: deployed.storeKeyUtil.address,
28 | StrategyLibV1: deployed.strategyLibV1.address,
29 | ValidationLibV1: deployed.validationLibV1.address,
30 | VaultLibV1: deployed.vaultLib.address
31 | }
32 | , deployed.store.address
33 | )
34 |
35 | const _store = await vaultDelegate.s()
36 | _store.should.equal(deployed.store.address)
37 |
38 | const version = await vaultDelegate.version()
39 | version.should.equal(key.toBytes32('v0.1'))
40 |
41 | const name = await vaultDelegate.getName()
42 | name.should.equal(key.PROTOCOL.CNAME.VAULT_DELEGATE)
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/test/specs/liquidity/engine/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Liquidity Engine Constructor and Views', () => {
13 | let store, deployed
14 |
15 | beforeEach(async () => {
16 | deployed = await deployDependencies()
17 | store = deployed.store
18 | })
19 |
20 | it('correctly deploys', async () => {
21 | const liquidityEngine = await deployer.deployWithLibraries(cache, 'LiquidityEngine', {
22 | AccessControlLibV1: deployed.accessControlLibV1.address,
23 | BaseLibV1: deployed.baseLibV1.address,
24 | NTransferUtilV2: deployed.transferLib.address,
25 | ProtoUtilV1: deployed.protoUtilV1.address,
26 | RegistryLibV1: deployed.registryLibV1.address,
27 | StoreKeyUtil: deployed.storeKeyUtil.address,
28 | StrategyLibV1: deployed.strategyLibV1.address,
29 | ValidationLibV1: deployed.validationLibV1.address
30 | }, store.address)
31 |
32 | const _store = await liquidityEngine.s()
33 |
34 | _store.should.equal(store.address)
35 |
36 | const version = await liquidityEngine.version()
37 | version.should.equal(key.toBytes32('v0.1'))
38 |
39 | const name = await liquidityEngine.getName()
40 | name.should.equal(key.PROTOCOL.CNAME.LIQUIDITY_ENGINE)
41 | })
42 | })
43 |
--------------------------------------------------------------------------------
/test/specs/liquidity/strategy/aave/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../../../util')
4 | const { deployDependencies } = require('../deps')
5 | const cache = null
6 | const CNAME_STRATEGY_AAVE = key.toBytes32('Aave Strategy')
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Aave Strategy Constructor', () => {
14 | let deployed, aaveLendingPool, aToken
15 |
16 | beforeEach(async () => {
17 | deployed = await deployDependencies()
18 |
19 | aToken = await deployer.deploy(cache, 'FakeToken', 'aToken', 'aToken', helper.ether(100_000_000), 18)
20 | aaveLendingPool = await deployer.deploy(cache, 'FakeAaveLendingPool', aToken.address)
21 | })
22 |
23 | it('correctly deploys', async () => {
24 | const aaveStrategy = await deployer.deployWithLibraries(cache, 'AaveStrategy', {
25 | AccessControlLibV1: deployed.accessControlLibV1.address,
26 | BaseLibV1: deployed.baseLibV1.address,
27 | NTransferUtilV2: deployed.transferLib.address,
28 | ProtoUtilV1: deployed.protoUtilV1.address,
29 | RegistryLibV1: deployed.registryLibV1.address,
30 | StoreKeyUtil: deployed.storeKeyUtil.address,
31 | ValidationLibV1: deployed.validationLibV1.address
32 | }, deployed.store.address, aaveLendingPool.address, aToken.address)
33 |
34 | ; (await aaveStrategy.getKey()).should.equal(ethers.utils.solidityKeccak256(['string', 'string', 'string', 'string'], ['lending', 'strategy', 'aave', 'v2']))
35 | ; (await aaveStrategy.version()).should.equal(key.toBytes32('v0.1'))
36 | ; (await aaveStrategy.getName()).should.equal(CNAME_STRATEGY_AAVE)
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault-factory/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('VaultFactory Constructor and Views', () => {
13 | let store, deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 |
18 | store = deployed.store
19 | })
20 |
21 | it('correctly deploys', async () => {
22 | const vault = await deployer.deployWithLibraries(cache, 'VaultFactory', {
23 | AccessControlLibV1: deployed.accessControlLibV1.address,
24 | BaseLibV1: deployed.baseLibV1.address,
25 | ProtoUtilV1: deployed.protoUtilV1.address,
26 | ValidationLibV1: deployed.validationLibV1.address,
27 | VaultFactoryLibV1: deployed.vaultFactoryLibV1.address
28 | }, store.address)
29 |
30 | const _store = await vault.s()
31 | _store.should.equal(store.address)
32 |
33 | const version = await vault.version()
34 | version.should.equal(key.toBytes32('v0.1'))
35 |
36 | const name = await vault.getName()
37 | name.should.equal(key.PROTOCOL.CNAME.VAULT_FACTORY)
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/calculate-liquidity.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Vault: calculateLiquidity', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly calculates the liquidity', async () => {
20 | const result = await deployed.vault.calculateLiquidity(helper.ether(1_000))
21 | result.should.equal(helper.ether(1_000, PRECISION))
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/calculate-pods.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Vault: calculatePods', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly calculates amount of pods', async () => {
20 | const result = await deployed.vault.calculatePods(helper.ether(1_000, PRECISION))
21 | result.should.equal(helper.ether(1_000))
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 | const cache = null
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Vault Constructor and Views', () => {
14 | let store, deployed
15 |
16 | beforeEach(async () => {
17 | deployed = await deployDependencies()
18 |
19 | store = deployed.store
20 | })
21 |
22 | it('correctly deploys', async () => {
23 | const coverKey = key.toBytes32('test')
24 | const liquidityToken = await deployer.deploy(cache, 'FakeToken', 'USDC Token', 'USDC', helper.ether(100_000_000, PRECISION), PRECISION)
25 |
26 | const vault = await deployer.deployWithLibraries(cache, 'Vault', {
27 | AccessControlLibV1: deployed.accessControlLibV1.address,
28 | BaseLibV1: deployed.baseLibV1.address,
29 | NTransferUtilV2: deployed.transferLib.address,
30 | ProtoUtilV1: deployed.protoUtilV1.address,
31 | RegistryLibV1: deployed.registryLibV1.address,
32 | ValidationLibV1: deployed.validationLibV1.address
33 | }, store.address, coverKey, 'Vault', 'VAULT', liquidityToken.address)
34 |
35 | const _store = await vault.s()
36 | _store.should.equal(store.address)
37 |
38 | const version = await vault.version()
39 | version.should.equal(key.toBytes32('v0.1'))
40 |
41 | const name = await vault.getName()
42 | name.should.equal(key.PROTOCOL.CNAME.LIQUIDITY_VAULT)
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/flash-fee.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployDependencies } = require('./deps')
4 |
5 | require('chai')
6 | .use(require('chai-as-promised'))
7 | .use(require('chai-bignumber')(BigNumber))
8 | .should()
9 |
10 | describe('Flashloan: flashFee', () => {
11 | let deployed
12 |
13 | before(async () => {
14 | deployed = await deployDependencies()
15 | })
16 |
17 | it('must get flashloan fee', async () => {
18 | const amount = 200
19 | const fee = 1 // Flash Loan Fee: 0.5%
20 |
21 | const result = await deployed.vault.flashFee(deployed.stablecoin.address, amount)
22 | result.should.equal(fee)
23 | })
24 | })
25 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/get-info.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Vault: getInfo', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly gets vault info', async () => {
20 | const [owner] = await ethers.getSigners()
21 |
22 | const result = await deployed.vault.getInfo(owner.address)
23 | result[0].should.equal(helper.ether(4_000_000))
24 | result[1].should.equal(helper.ether(4_000_000, PRECISION))
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/max-flash-loan.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Flashloan: max flash loan', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('must get max flashloan amount', async () => {
20 | const result = await deployed.vault.maxFlashLoan(deployed.stablecoin.address)
21 |
22 | result.should.equal(helper.ether(4_000_000, PRECISION))
23 | })
24 | })
25 |
--------------------------------------------------------------------------------
/test/specs/liquidity/vault/transfer-governance.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const PRECISION = helper.STABLECOIN_DECIMALS
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Vault: transferGovernance', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('reverts when coverKey is invalid', async () => {
20 | const coverKey = key.toBytes32('foo-bar2')
21 | const amount = helper.ether(1_000, PRECISION)
22 | const address = helper.zero1
23 |
24 | await deployed.vault.transferGovernance(coverKey, address, amount)
25 | .should.be.rejectedWith('Forbidden')
26 | })
27 |
28 | it('reverts when invalid amount is supplied', async () => {
29 | const coverKey = key.toBytes32('foo-bar')
30 | const amount = helper.ether(0)
31 | const address = helper.zero1
32 |
33 | await deployed.vault.transferGovernance(coverKey, address, amount)
34 | .should.be.rejectedWith('Please specify amount')
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/test/specs/policy-admin/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Policy Admin Constructor and Views', () => {
13 | let deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 | })
18 |
19 | it('correctly deploys', async () => {
20 | const policyAdminContract = await deployer.deployWithLibraries(cache, 'PolicyAdmin', {
21 | AccessControlLibV1: deployed.accessControlLibV1.address,
22 | BaseLibV1: deployed.baseLibV1.address,
23 | PolicyHelperV1: deployed.policyHelperV1.address,
24 | RoutineInvokerLibV1: deployed.routineInvokerLibV1.address,
25 | StoreKeyUtil: deployed.storeKeyUtil.address,
26 | ValidationLibV1: deployed.validationLibV1.address
27 | }, deployed.store.address)
28 |
29 | const version = await policyAdminContract.version()
30 | const name = await policyAdminContract.getName()
31 |
32 | version.should.equal(key.toBytes32('v0.1'))
33 | name.should.equal(key.PROTOCOL.CNAME.POLICY_ADMIN)
34 | })
35 | })
36 |
--------------------------------------------------------------------------------
/test/specs/policy/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Policy Constructor', () => {
13 | let deployed, registry, policy
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 |
18 | registry = await deployer.deployWithLibraries(cache, 'MockRegistryClient', {
19 | RegistryLibV1: deployed.registryLibV1.address
20 | }, deployed.store.address)
21 | })
22 |
23 | it('correctly deploys', async () => {
24 | policy = await deployer.deployWithLibraries(cache, 'Policy', {
25 | AccessControlLibV1: deployed.accessControlLibV1.address,
26 | BaseLibV1: deployed.baseLibV1.address,
27 | CoverUtilV1: deployed.coverUtilV1.address,
28 | PolicyHelperV1: deployed.policyHelperV1.address,
29 | ProtoUtilV1: deployed.protoUtilV1.address,
30 | StrategyLibV1: deployed.strategyLibV1.address,
31 | ValidationLibV1: deployed.validationLibV1.address
32 | }, deployed.store.address)
33 |
34 | await deployed.protocol.addContract(key.PROTOCOL.CNS.COVER_POLICY, policy.address)
35 |
36 | const version = await policy.version()
37 | const name = await policy.getName()
38 |
39 | version.should.equal(key.toBytes32('v0.1'))
40 | name.should.equal(key.PROTOCOL.CNAME.POLICY)
41 | })
42 |
43 | it('must correctly return policy contract address from the registry', async () => {
44 | (await registry.getPolicyContract()).should.equal(policy.address)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/specs/pool/bond/calculate-tokens-for-lp.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const { ethers } = require('hardhat')
6 | const MINUTES = 60
7 | const cache = null
8 |
9 | require('chai')
10 | .use(require('chai-as-promised'))
11 | .use(require('chai-bignumber')(BigNumber))
12 | .should()
13 |
14 | describe('Bond: Calculate Tokens for LP', () => {
15 | let deployed, store, pool, payload
16 |
17 | before(async () => {
18 | deployed = await deployDependencies()
19 |
20 | store = deployed.store
21 |
22 | pool = await deployer.deployWithLibraries(cache, 'BondPool', {
23 | AccessControlLibV1: deployed.accessControlLibV1.address,
24 | BondPoolLibV1: deployed.bondPoolLibV1.address,
25 | BaseLibV1: deployed.baseLibV1.address,
26 | PriceLibV1: deployed.priceLibV1.address,
27 | ValidationLibV1: deployed.validationLibV1.address
28 | }, store.address)
29 |
30 | await deployed.protocol.addContract(key.PROTOCOL.CNS.BOND_POOL, pool.address)
31 |
32 | payload = {
33 | lpToken: deployed.npmStablecoinPair.address,
34 | treasury: helper.randomAddress(),
35 | bondDiscountRate: helper.percentage(1),
36 | maxBondAmount: helper.ether(100_000),
37 | vestingTerm: (5 * MINUTES).toString(),
38 | npmToTopUpNow: helper.ether(10_000_000)
39 | }
40 |
41 | await deployed.npm.approve(pool.address, ethers.constants.MaxUint256)
42 |
43 | await pool.setup(payload)
44 | })
45 |
46 | it('correctly calculates NPM tokens for specified LP tokens', async () => {
47 | const npmTokens = await pool.calculateTokensForLp(helper.ether(200))
48 | npmTokens.should.equal('101010101010101010101')
49 | })
50 | })
51 |
--------------------------------------------------------------------------------
/test/specs/pool/bond/ctor.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Bond Pool Constructor and Views', () => {
13 | let deployed, registry, bondPool
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 |
18 | registry = await deployer.deployWithLibraries(cache, 'MockRegistryClient', {
19 | RegistryLibV1: deployed.registryLibV1.address
20 | }, deployed.store.address)
21 | })
22 |
23 | it('correctly deploys', async () => {
24 | bondPool = await deployer.deployWithLibraries(cache, 'BondPool', {
25 | AccessControlLibV1: deployed.accessControlLibV1.address,
26 | BondPoolLibV1: deployed.bondPoolLibV1.address,
27 | BaseLibV1: deployed.baseLibV1.address,
28 | PriceLibV1: deployed.priceLibV1.address,
29 | ValidationLibV1: deployed.validationLibV1.address
30 | }, deployed.store.address)
31 |
32 | await deployed.protocol.addContract(key.PROTOCOL.CNS.BOND_POOL, bondPool.address)
33 |
34 | bondPool.address.should.not.be.empty
35 | bondPool.address.should.not.equal(helper.zerox)
36 | ; (await bondPool.version()).should.equal(key.toBytes32('v0.1'))
37 | ; (await bondPool.getName()).should.equal(key.PROTOCOL.CNAME.BOND_POOL)
38 | })
39 |
40 | it('must correctly return bond pool contract address from the registry', async () => {
41 | (await registry.getBondPoolContract()).should.equal(bondPool.address)
42 | })
43 | })
44 |
--------------------------------------------------------------------------------
/test/specs/pool/bond/npm-token-price.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const { ethers } = require('hardhat')
6 | const MINUTES = 60
7 | const cache = null
8 |
9 | require('chai')
10 | .use(require('chai-as-promised'))
11 | .use(require('chai-bignumber')(BigNumber))
12 | .should()
13 |
14 | describe('Bond: NPM Token Price', () => {
15 | let deployed, store, pool, payload
16 |
17 | before(async () => {
18 | deployed = await deployDependencies()
19 |
20 | store = deployed.store
21 |
22 | pool = await deployer.deployWithLibraries(cache, 'BondPool', {
23 | AccessControlLibV1: deployed.accessControlLibV1.address,
24 | BondPoolLibV1: deployed.bondPoolLibV1.address,
25 | BaseLibV1: deployed.baseLibV1.address,
26 | PriceLibV1: deployed.priceLibV1.address,
27 | ValidationLibV1: deployed.validationLibV1.address
28 | }, store.address)
29 |
30 | await deployed.protocol.addContract(key.PROTOCOL.CNS.BOND_POOL, pool.address)
31 |
32 | payload = {
33 | lpToken: deployed.npmStablecoinPair.address,
34 | treasury: helper.randomAddress(),
35 | bondDiscountRate: helper.percentage(1),
36 | maxBondAmount: helper.ether(100_000),
37 | vestingTerm: (5 * MINUTES).toString(),
38 | npmToTopUpNow: helper.ether(10_000_000)
39 | }
40 |
41 | await deployed.npm.approve(pool.address, ethers.constants.MaxUint256)
42 |
43 | await pool.setup(payload)
44 | })
45 |
46 | it('correctly returns the NPM token price', async () => {
47 | const price = await pool.getNpmMarketPrice()
48 | price.should.equal(helper.ether(2))
49 | })
50 | })
51 |
--------------------------------------------------------------------------------
/test/specs/pool/staking/ctor-vfns.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer, key } = require('../../../../util')
4 | const { deployDependencies } = require('./deps')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Staking Pool Constructor and Views', () => {
13 | let store, deployed
14 |
15 | before(async () => {
16 | deployed = await deployDependencies()
17 |
18 | store = deployed.store
19 | })
20 |
21 | it('correctly deploys', async () => {
22 | const stakingPoolContract = await deployer.deployWithLibraries(cache, 'StakingPools', {
23 | AccessControlLibV1: deployed.accessControlLibV1.address,
24 | BaseLibV1: deployed.baseLibV1.address,
25 | StakingPoolCoreLibV1: deployed.stakingPoolCoreLibV1.address,
26 | StakingPoolLibV1: deployed.stakingPoolLibV1.address,
27 | StoreKeyUtil: deployed.storeKeyUtil.address,
28 | ValidationLibV1: deployed.validationLibV1.address
29 | }, store.address)
30 |
31 | stakingPoolContract.address.should.not.be.empty
32 | stakingPoolContract.address.should.not.equal(helper.zerox)
33 | ; (await stakingPoolContract.version()).should.equal(key.toBytes32('v0.1'))
34 | ; (await stakingPoolContract.getName()).should.equal(key.PROTOCOL.CNAME.STAKING_POOL)
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/test/specs/store/count-address-array-items.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: count address array items', () => {
12 | let store, items, k
13 |
14 | before(async () => {
15 | items = [helper.randomAddress(), helper.randomAddress(), helper.randomAddress(), helper.randomAddress()]
16 |
17 | store = await deployer.deploy(cache, 'Store')
18 |
19 | k = key.toBytes32('test:address:array:item')
20 |
21 | for (const item of items) {
22 | await store.setAddressArrayItem(k, item)
23 | await store.setAddressArrayItem(k, item) // same item added multiple times should not increase the count
24 | }
25 | })
26 |
27 | it('must correctly count address array items', async () => {
28 | const result = await store.countAddressArrayItems(k)
29 | result.should.equal(items.length.toString())
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/test/specs/store/delete-address-array-item-by-index.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: delete address array item by index', () => {
12 | let store, items, k
13 |
14 | before(async () => {
15 | items = [helper.randomAddress(), helper.randomAddress(), helper.randomAddress(), helper.randomAddress(), helper.randomAddress()]
16 | store = await deployer.deploy(cache, 'Store')
17 |
18 | k = key.toBytes32('test:address:array:item')
19 |
20 | for (const item of items) {
21 | await store.setAddressArrayItem(k, item)
22 | }
23 | })
24 |
25 | it('must correctly delete address array items by indices', async () => {
26 | const index = 1
27 | await store.deleteAddressArrayItemByIndex(k, index)
28 | items.splice(index, 1)
29 |
30 | const result = await store.getAddressArray(k)
31 | ; [...result].sort().should.deep.equal([...items].sort())
32 | })
33 |
34 | it('must revert with an error if an invalid index is specified', async () => {
35 | await store.deleteAddressArrayItemByIndex(k, 10)
36 | .should.be.rejectedWith('Invalid index')
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/test/specs/store/delete-address-array-item.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: delete address array item', () => {
12 | let store, items, k, toDelete
13 |
14 | before(async () => {
15 | items = [helper.randomAddress(), helper.randomAddress(), helper.randomAddress(), helper.randomAddress(), helper.randomAddress()]
16 | toDelete = items[2]
17 |
18 | store = await deployer.deploy(cache, 'Store')
19 |
20 | k = key.toBytes32('test:address:array:item')
21 |
22 | for (const item of items) {
23 | await store.setAddressArrayItem(k, item)
24 | }
25 | })
26 |
27 | it('must correctly delete an address array item', async () => {
28 | await store.deleteAddressArrayItem(k, toDelete)
29 |
30 | const result = await store.getAddressArray(k)
31 | ; [...result].sort().should.deep.equal(items.filter(x => x !== toDelete).sort())
32 | })
33 |
34 | it('must revert with an error if an invalid address is specified', async () => {
35 | await store.deleteAddressArrayItem(k, helper.randomAddress())
36 | .should.be.rejectedWith('Not found')
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/test/specs/store/get-address-array-item-by-index.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key, helper } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: get address array item by index', () => {
12 | let store, items, k
13 |
14 | before(async () => {
15 | items = [helper.randomAddress(), helper.randomAddress(), helper.randomAddress()]
16 | store = await deployer.deploy(cache, 'Store')
17 |
18 | k = key.toBytes32('test:address:array:item')
19 |
20 | for (const item of items) {
21 | await store.setAddressArrayItem(k, item)
22 | }
23 | })
24 |
25 | it('must correctly get address array items by indices', async () => {
26 | for (const i in items) {
27 | const item = items[i]
28 | const result = await store.getAddressArrayItemByIndex(k, i)
29 |
30 | result.should.equal(item)
31 | }
32 | })
33 |
34 | it('must revert with an error if an invalid index is specified', async () => {
35 | await store.getAddressArrayItemByIndex(k, 10)
36 | .should.be.rejectedWith('Invalid index')
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/test/specs/store/get-address-values.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer, key } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: get address values', () => {
12 | let store
13 |
14 | before(async () => {
15 | store = await deployer.deploy(cache, 'Store')
16 | })
17 |
18 | it('must correctly get the stored address values', async () => {
19 | const keys = [key.toBytes32('test:address1'), key.toBytes32('test:address2')]
20 |
21 | const values = [
22 | helper.randomAddress(),
23 | helper.randomAddress()
24 | ]
25 |
26 | for (const i in keys) {
27 | await store.setAddress(keys[i], values[i])
28 | }
29 |
30 | const result = await store.getAddressValues(keys)
31 | result.should.deep.equal(values)
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/test/specs/store/get-uint-values.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const { helper, deployer, key } = require('../../../util')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Store: get uint values', () => {
13 | let store
14 |
15 | before(async () => {
16 | store = await deployer.deploy(cache, 'Store')
17 | })
18 |
19 | it('must correctly get the stored uint values', async () => {
20 | const keys = [key.toBytes32('test:uint1'), key.toBytes32('test:uint2')]
21 |
22 | const values = [
23 | ethers.BigNumber.from(helper.getRandomNumber(10000000, 100000000).toString()),
24 | ethers.BigNumber.from(helper.getRandomNumber(10000000, 100000000).toString())
25 | ]
26 |
27 | for (const i in keys) {
28 | await store.setUint(keys[i], values[i])
29 | }
30 |
31 | const result = await store.getUintValues(keys)
32 |
33 | for (const i in result) {
34 | result[i].should.equal(values[i])
35 | }
36 | })
37 | })
38 |
--------------------------------------------------------------------------------
/test/specs/store/pausable.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { deployer, key } = require('../../../util')
4 | const cache = null
5 |
6 | require('chai')
7 | .use(require('chai-as-promised'))
8 | .use(require('chai-bignumber')(BigNumber))
9 | .should()
10 |
11 | describe('Store: Pausable', () => {
12 | let store
13 |
14 | before(async () => {
15 | store = await deployer.deploy(cache, 'Store')
16 | })
17 |
18 | it('must allow a pauser to pause the store', async () => {
19 | const [owner] = await ethers.getSigners()
20 | await store.setPausers([owner.address], [true])
21 | await store.pause()
22 |
23 | const state = await store.paused()
24 |
25 | state.should.be.true
26 | })
27 |
28 | it('must throw if the store is paused', async () => {
29 | await store.setUint(key.toBytes32('test'), '1')
30 | .should.be.rejectedWith('Pausable: paused')
31 | })
32 |
33 | it('must allow the owner to unpause the store', async () => {
34 | await store.unpause()
35 |
36 | const state = await store.paused()
37 | state.should.be.false
38 | })
39 |
40 | it('must allow store member to update the store', async () => {
41 | await store.setUint(key.toBytes32('test'), '1')
42 | .should.not.be.rejected
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/test/specs/store/set-address.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const { deployer, key, helper } = require('../../../util')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Store: set address', () => {
13 | let store
14 |
15 | before(async () => {
16 | store = await deployer.deploy(cache, 'Store')
17 | })
18 |
19 | it('must correctly set address', async () => {
20 | const k = key.toBytes32('test:address')
21 | const value = helper.randomAddress()
22 | await store.setAddress(k, value)
23 |
24 | const result = await store.getAddress(k)
25 | result.should.equal(value)
26 | })
27 |
28 | it('must revert if the store is paused', async () => {
29 | const [owner] = await ethers.getSigners()
30 | await store.setPausers([owner.address], [true])
31 | await store.pause()
32 |
33 | const k = key.toBytes32('test:address')
34 | const value = helper.randomAddress()
35 |
36 | await store.setAddress(k, value)
37 | .should.be.rejectedWith('Pausable: paused')
38 |
39 | await store.unpause()
40 |
41 | await store.setAddress(k, value)
42 | .should.not.be.rejected
43 | })
44 |
45 | it('must revert if the sender is not a store or protocol member', async () => {
46 | const [, bob] = await ethers.getSigners()
47 |
48 | const k = key.toBytes32('test:address')
49 | const value = helper.randomAddress()
50 |
51 | await store.connect(bob).setAddress(k, value)
52 | .should.be.rejectedWith('Forbidden')
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/test/specs/store/set-bool.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const { deployer, key } = require('../../../util')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Store: set bool', () => {
13 | let store
14 |
15 | before(async () => {
16 | store = await deployer.deploy(cache, 'Store')
17 | })
18 |
19 | it('must correctly set bool', async () => {
20 | const k = key.toBytes32('test:bool')
21 | const value = Math.random() < 0.5
22 | await store.setBool(k, value)
23 |
24 | const result = await store.getBool(k)
25 | result.should.equal(value)
26 | })
27 |
28 | it('must revert if the store is paused', async () => {
29 | const [owner] = await ethers.getSigners()
30 | await store.setPausers([owner.address], [true])
31 | await store.pause()
32 |
33 | const k = key.toBytes32('test:bool')
34 | const value = Math.random() < 0.5
35 |
36 | await store.setBool(k, value)
37 | .should.be.rejectedWith('Pausable: paused')
38 |
39 | await store.unpause()
40 |
41 | await store.setBool(k, value)
42 | .should.not.be.rejected
43 | })
44 |
45 | it('must revert if the sender is not a store or protocol member', async () => {
46 | const [, bob] = await ethers.getSigners()
47 |
48 | const k = key.toBytes32('test:bool')
49 | const value = Math.random() < 0.5
50 |
51 | await store.connect(bob).setBool(k, value)
52 | .should.be.rejectedWith('Forbidden')
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/test/specs/store/set-bytes.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const uuid = require('uuid')
5 | const { helper, deployer, key } = require('../../../util')
6 | const cache = null
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Store: set bytes', () => {
14 | let store
15 |
16 | before(async () => {
17 | store = await deployer.deploy(cache, 'Store')
18 | })
19 |
20 | it('must correctly set bytes', async () => {
21 | const k = key.toBytes32('test:bytes')
22 | const value = helper.stringToHex(uuid.v4())
23 | await store.setBytes(k, value)
24 |
25 | const result = await store.getBytes(k)
26 | result.should.equal(value)
27 | })
28 |
29 | it('must revert if the store is paused', async () => {
30 | const [owner] = await ethers.getSigners()
31 | await store.setPausers([owner.address], [true])
32 | await store.pause()
33 |
34 | const k = key.toBytes32('test:bytes')
35 | const value = helper.stringToHex(uuid.v4())
36 |
37 | await store.setBytes(k, value)
38 | .should.be.rejectedWith('Pausable: paused')
39 |
40 | await store.unpause()
41 |
42 | await store.setBytes(k, value)
43 | .should.not.be.rejected
44 | })
45 |
46 | it('must revert if the sender is not a store or protocol member', async () => {
47 | const [, bob] = await ethers.getSigners()
48 |
49 | const k = key.toBytes32('test:bytes')
50 | const value = helper.stringToHex(uuid.v4())
51 |
52 | await store.connect(bob).setBytes(k, value)
53 | .should.be.rejectedWith('Forbidden')
54 | })
55 | })
56 |
--------------------------------------------------------------------------------
/test/specs/store/set-bytes32.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const uuid = require('uuid')
5 | const { deployer, key } = require('../../../util')
6 | const cache = null
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Store: set bytes32', () => {
14 | let store
15 |
16 | before(async () => {
17 | store = await deployer.deploy(cache, 'Store')
18 | })
19 |
20 | it('must correctly set bytes32', async () => {
21 | const k = key.toBytes32('test:bytes32')
22 | const value = key.toBytes32(uuid.v4().substring(0, 30))
23 | await store.setBytes32(k, value)
24 |
25 | const result = await store.getBytes32(k)
26 | result.should.equal(value)
27 | })
28 |
29 | it('must revert if the store is paused', async () => {
30 | const [owner] = await ethers.getSigners()
31 | await store.setPausers([owner.address], [true])
32 | await store.pause()
33 |
34 | const k = key.toBytes32('test:bytes32')
35 | const value = key.toBytes32(uuid.v4().substring(0, 30))
36 |
37 | await store.setBytes32(k, value)
38 | .should.be.rejectedWith('Pausable: paused')
39 |
40 | await store.unpause()
41 |
42 | await store.setBytes32(k, value)
43 | .should.not.be.rejected
44 | })
45 |
46 | it('must revert if the sender is not a store or protocol member', async () => {
47 | const [, bob] = await ethers.getSigners()
48 |
49 | const k = key.toBytes32('test:bytes32')
50 | const value = key.toBytes32(uuid.v4().substring(0, 30))
51 |
52 | await store.connect(bob).setBytes32(k, value)
53 | .should.be.rejectedWith('Forbidden')
54 | })
55 | })
56 |
--------------------------------------------------------------------------------
/test/specs/store/set-int.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const { helper, deployer, key } = require('../../../util')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Store: set int', () => {
13 | let store
14 |
15 | before(async () => {
16 | store = await deployer.deploy(cache, 'Store')
17 | })
18 |
19 | it('must correctly set int', async () => {
20 | const k = key.toBytes32('test:int')
21 | const value = helper.getRandomNumber(-100000000, 100000000).toString()
22 | await store.setInt(k, value)
23 |
24 | const result = await store.getInt(k)
25 | result.should.equal(value)
26 | })
27 |
28 | it('must revert if the store is paused', async () => {
29 | const [owner] = await ethers.getSigners()
30 | await store.setPausers([owner.address], [true])
31 | await store.pause()
32 |
33 | const k = key.toBytes32('test:int')
34 | const value = helper.getRandomNumber(-100000000, 100000000).toString()
35 |
36 | await store.setInt(k, value)
37 | .should.be.rejectedWith('Pausable: paused')
38 |
39 | await store.unpause()
40 |
41 | await store.setInt(k, value)
42 | .should.not.be.rejected
43 | })
44 |
45 | it('must revert if the sender is not a store or protocol member', async () => {
46 | const [, bob] = await ethers.getSigners()
47 |
48 | const k = key.toBytes32('test:int')
49 | const value = helper.getRandomNumber(-10000000, 100000000).toString()
50 |
51 | await store.connect(bob).setInt(k, value)
52 | .should.be.rejectedWith('Forbidden')
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/test/specs/store/set-string.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const uuid = require('uuid')
5 | const { deployer, key } = require('../../../util')
6 | const cache = null
7 |
8 | require('chai')
9 | .use(require('chai-as-promised'))
10 | .use(require('chai-bignumber')(BigNumber))
11 | .should()
12 |
13 | describe('Store: set string', () => {
14 | let store
15 |
16 | before(async () => {
17 | store = await deployer.deploy(cache, 'Store')
18 | })
19 |
20 | it('must correctly set string', async () => {
21 | const k = key.toBytes32('test:string')
22 | const value = uuid.v4()
23 | await store.setString(k, value)
24 |
25 | const result = await store.getString(k)
26 | result.should.equal(value)
27 | })
28 |
29 | it('must revert if the store is paused', async () => {
30 | const [owner] = await ethers.getSigners()
31 | await store.setPausers([owner.address], [true])
32 | await store.pause()
33 |
34 | const k = key.toBytes32('test:string')
35 | const value = uuid.v4()
36 |
37 | await store.setString(k, value)
38 | .should.be.rejectedWith('Pausable: paused')
39 |
40 | await store.unpause()
41 |
42 | await store.setString(k, value)
43 | .should.not.be.rejected
44 | })
45 |
46 | it('must revert if the sender is not a store or protocol member', async () => {
47 | const [, bob] = await ethers.getSigners()
48 |
49 | const k = key.toBytes32('test:string')
50 | const value = uuid.v4()
51 |
52 | await store.connect(bob).setString(k, value)
53 | .should.be.rejectedWith('Forbidden')
54 | })
55 | })
56 |
--------------------------------------------------------------------------------
/test/specs/store/set-uint.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { ethers } = require('hardhat')
4 | const { helper, deployer, key } = require('../../../util')
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Store: set uint', () => {
13 | let store
14 |
15 | before(async () => {
16 | store = await deployer.deploy(cache, 'Store')
17 | })
18 |
19 | it('must correctly set uint', async () => {
20 | const k = key.toBytes32('test:uint')
21 | const value = helper.getRandomNumber(10000000, 100000000).toString()
22 | await store.setUint(k, value)
23 |
24 | const result = await store.getUint(k)
25 | result.should.equal(value)
26 | })
27 |
28 | it('must revert if the store is paused', async () => {
29 | const [owner] = await ethers.getSigners()
30 | await store.setPausers([owner.address], [true])
31 | await store.pause()
32 |
33 | const k = key.toBytes32('test:uint')
34 | const value = helper.getRandomNumber(10000000, 100000000).toString()
35 |
36 | await store.setUint(k, value)
37 | .should.be.rejectedWith('Pausable: paused')
38 |
39 | await store.unpause()
40 |
41 | await store.setUint(k, value)
42 | .should.not.be.rejected
43 | })
44 |
45 | it('must revert if the sender is not a store or protocol member', async () => {
46 | const [, bob] = await ethers.getSigners()
47 |
48 | const k = key.toBytes32('test:uint')
49 | const value = helper.getRandomNumber(10000000, 100000000).toString()
50 |
51 | await store.connect(bob).setUint(k, value)
52 | .should.be.rejectedWith('Forbidden')
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/test/specs/token/delayable.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | const BigNumber = require('bignumber.js')
3 | const { helper, deployer } = require('../../../util')
4 | const DAYS = 86400
5 | const cache = null
6 |
7 | require('chai')
8 | .use(require('chai-as-promised'))
9 | .use(require('chai-bignumber')(BigNumber))
10 | .should()
11 |
12 | describe('Delayable', () => {
13 | it('should deploy correctly', async () => {
14 | const minDelay = 1 * DAYS
15 | const proposers = [helper.randomAddress()]
16 | const executors = [helper.randomAddress()]
17 |
18 | const delayable = await deployer.deploy(cache, 'Delayable', minDelay, proposers, executors)
19 | const { events } = await delayable.deployTransaction.wait()
20 | const event = events.find(x => x.event === 'MinDelayChange')
21 |
22 | event.args.oldDuration.should.equal('0')
23 | event.args.newDuration.should.equal(minDelay.toString())
24 | })
25 | })
26 |
--------------------------------------------------------------------------------
/truffle-config.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | mocha: {
3 | timeout: 250000
4 | },
5 | compilers: {
6 | solc: {
7 | version: '0.8.17',
8 | docker: false,
9 | settings: {
10 | optimizer: {
11 | enabled: true,
12 | runs: 200
13 | },
14 | evmVersion: 'istanbul'
15 | }
16 | }
17 | },
18 | db: {
19 | enabled: false
20 | }
21 | }
22 |
23 | module.exports = config
24 |
--------------------------------------------------------------------------------
/util/analyzers/validators/access-control.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const hasAcl = code.indexOf('AccessControl') > -1
9 | const hasCallerCheck = code.indexOf('callerMustBe') > -1
10 | const hasOwnerCheck = code.indexOf('onlyOwner') > -1
11 | const isLibrary = (name || '').split('/').indexOf('libraries') > -1
12 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-acl') === -1 && code.toLowerCase().indexOf('@custom:suppress-acl') === -1
13 |
14 | if (!(hasAcl || hasCallerCheck || hasOwnerCheck || isLibrary) && suppressionMissing) {
15 | return '\x1b[31m' + '* Access control logic not found. Are you sure this function should be publicly accessible?' + '\x1b[0m'
16 | }
17 |
18 | return null
19 | }
20 |
21 | module.exports = validate
22 |
--------------------------------------------------------------------------------
/util/analyzers/validators/accidental-zero.js:
--------------------------------------------------------------------------------
1 | const { isLib } = require('./lib')
2 | const { isMock } = require('./mock')
3 |
4 | const validate = async (code, _, name) => {
5 | if (isLib(name) || isMock(name)) {
6 | return null
7 | }
8 |
9 | const supressionMissing = code.toLowerCase().indexOf('@suppress-accidental-zero') === -1 && code.toLowerCase().indexOf('@custom:suppress-accidental-zero') === -1
10 | const hasLogic = code.toLowerCase().indexOf('> ') > -1 || code.toLowerCase().indexOf('>= ') > -1 || code.toLowerCase().indexOf('< ') > -1 || code.toLowerCase().indexOf('<= ') > -1
11 |
12 | if (supressionMissing && hasLogic) {
13 | return '\x1b[31m' + '* Warning: Ensure that either of these values are not unassigned or accidentally zero' + '\x1b[0m'
14 | }
15 |
16 | return null
17 | }
18 |
19 | module.exports = validate
20 |
--------------------------------------------------------------------------------
/util/analyzers/validators/address.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, selector, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const addressArgs = selector.parameters
9 | .parameters.filter(x => x.typeName.name === 'address' &&
10 | ['account', 'to', 'from', 'v', 'sendTo'].indexOf(x.name) === -1)
11 |
12 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-address-trust-issue') === -1 && code.toLowerCase().indexOf('@custom:suppress-address-trust-issue') === -1
13 |
14 | if (addressArgs.length && suppressionMissing) {
15 | return '\x1b[31m' + `* Ensure [${addressArgs.map(x => x.name).join(',')}] can be trusted. Ensure this function has AccessControl logic. Ensure you validate address before using.` + '\x1b[0m'
16 | }
17 |
18 | return null
19 | }
20 |
21 | module.exports = validate
22 |
--------------------------------------------------------------------------------
/util/analyzers/validators/erc-20.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-malicious-erc20') === -1 && code.toLowerCase().indexOf('@custom:suppress-malicious-erc') === -1
8 |
9 | if (code.toLowerCase().indexOf('erc20') > -1 && suppressionMissing) {
10 | return '\x1b[31m' + '* Ensure that you validate this ERC-20 token instance if the address came from user input' + '\x1b[0m'
11 | }
12 |
13 | return null
14 | }
15 |
16 | module.exports = validate
17 |
--------------------------------------------------------------------------------
/util/analyzers/validators/fraction.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-division') === -1 && code.toLowerCase().indexOf('@custom:suppress-division') === -1
9 |
10 | if (code.toLowerCase().indexOf('div(') > -1 && suppressionMissing) {
11 | return '\x1b[31m' + '* Warning: Please ensure the division(s) here does not end up producing zero values.' + '\x1b[0m'
12 | }
13 |
14 | if (code.toLowerCase().indexOf(' / ') > -1 && suppressionMissing) {
15 | return '\x1b[31m' + '* Warning: Please ensure the division(s) here does not end up producing zero values.' + '\x1b[0m'
16 | }
17 |
18 | return null
19 | }
20 |
21 | module.exports = validate
22 |
--------------------------------------------------------------------------------
/util/analyzers/validators/index.js:
--------------------------------------------------------------------------------
1 | const acl = require('./access-control')
2 | const address = require('./address')
3 | const erc20 = require('./erc-20')
4 | const fraction = require('./fraction')
5 | const initialization = require('./initialization')
6 | const nonReentrancy = require('./non-reentrancy')
7 | const notImplemented = require('./not-implemented')
8 | const pausable = require('./pausable')
9 | const revert = require('./revert')
10 | const subtraction = require('./subtraction')
11 | const todo = require('./todo')
12 | const zero = require('./zero-value')
13 | const accidentalZero = require('./accidental-zero')
14 |
15 | module.exports = [acl, address, erc20, fraction, initialization, nonReentrancy, notImplemented, pausable, revert, subtraction, todo, zero, accidentalZero]
16 |
--------------------------------------------------------------------------------
/util/analyzers/validators/initialization.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-initialization') === -1 && code.toLowerCase().indexOf('@custom:suppress-initialization') === -1
8 |
9 | if (code.toLowerCase().indexOf('function initia') > -1 && suppressionMissing) {
10 | return '\x1b[31m' + '* Ensure that there is access control for this initializer' + '\x1b[0m'
11 | }
12 |
13 | return null
14 | }
15 |
16 | module.exports = validate
17 |
--------------------------------------------------------------------------------
/util/analyzers/validators/lib.js:
--------------------------------------------------------------------------------
1 | const isLib = (name) => {
2 | const contract = (name || '').toLowerCase().split('/').pop()
3 |
4 | if (contract.indexOf('lib') > -1 || contract.indexOf('util') > -1 || contract.indexOf('helper') > -1) {
5 | return true
6 | }
7 |
8 | return false
9 | }
10 |
11 | module.exports = { isLib }
12 |
--------------------------------------------------------------------------------
/util/analyzers/validators/mock.js:
--------------------------------------------------------------------------------
1 | const isMock = (name) => {
2 | if ((name || '').toLowerCase().split('/').indexOf('mock') > -1) {
3 | return true
4 | }
5 |
6 | if ((name || '').toLowerCase().split('/').indexOf('fake') > -1) {
7 | return true
8 | }
9 |
10 | return false
11 | }
12 |
13 | module.exports = { isMock }
14 |
--------------------------------------------------------------------------------
/util/analyzers/validators/non-reentrancy.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | if ((name || '').split('/').indexOf('libraries') > -1) {
9 | return null
10 | }
11 |
12 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-reentrancy') === -1 && code.toLowerCase().indexOf('@custom:suppress-reentrancy') === -1
13 |
14 | if (code.indexOf('nonReentrant') === -1 && suppressionMissing) {
15 | return '\x1b[31m' + '* Non Reentrancy logic not found. Are you sure this function should be publicly accessible?' + '\x1b[0m'
16 | }
17 |
18 | return null
19 | }
20 |
21 | module.exports = validate
22 |
--------------------------------------------------------------------------------
/util/analyzers/validators/not-implemented.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | if (code.toLowerCase().indexOf('not implemented') > -1 || code.toLowerCase().indexOf('to-do') > -1) {
9 | return '\x1b[31m' + '* Error: implement the missing functionalities' + '\x1b[0m'
10 | }
11 |
12 | return null
13 | }
14 |
15 | module.exports = validate
16 |
--------------------------------------------------------------------------------
/util/analyzers/validators/pausable.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const hasPausable = code.toLowerCase().indexOf('pause') > -1
9 | const isLibrary = (name || '').split('/').indexOf('libraries') > -1
10 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-pausable') === -1 && code.toLowerCase().indexOf('@custom:suppress-pausable') === -1
11 |
12 | if (!(hasPausable || isLibrary) && suppressionMissing) {
13 | return '\x1b[31m' + '* Pausable logic not found' + '\x1b[0m'
14 | }
15 |
16 | return null
17 | }
18 |
19 | module.exports = validate
20 |
--------------------------------------------------------------------------------
/util/analyzers/validators/revert.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-revert') === -1 && code.toLowerCase().indexOf('@custom:suppress-revert') === -1
9 |
10 | if (code.toLowerCase().indexOf('revert') > -1 && suppressionMissing) {
11 | return '\x1b[31m' + '* Ensure that the usage of revert is correct' + '\x1b[0m'
12 | }
13 |
14 | return null
15 | }
16 |
17 | module.exports = validate
18 |
--------------------------------------------------------------------------------
/util/analyzers/validators/subtraction.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | const suppressionMissing = code.toLowerCase().indexOf('@suppress-subtraction') === -1 && code.toLowerCase().indexOf('@custom:suppress-subtraction') === -1
9 |
10 | if (code.toLowerCase().indexOf('subtract') > -1 && suppressionMissing) {
11 | return '\x1b[31m' + '* Warning: Please ensure this subtraction does not result in an underflow.' + '\x1b[0m'
12 | }
13 |
14 | if (code.toLowerCase().indexOf(' - ') > -1 && suppressionMissing) {
15 | return '\x1b[31m' + '* Warning: Please ensure this subtraction does not result in an underflow.' + '\x1b[0m'
16 | }
17 |
18 | return null
19 | }
20 |
21 | module.exports = validate
22 |
--------------------------------------------------------------------------------
/util/analyzers/validators/todo.js:
--------------------------------------------------------------------------------
1 | const { isMock } = require('./mock')
2 |
3 | const validate = async (code, _, name) => {
4 | if (isMock(name)) {
5 | return null
6 | }
7 |
8 | if (code.toLowerCase().indexOf('todo') > -1 || code.toLowerCase().indexOf('to-do') > -1) {
9 | return '\x1b[31m' + '* Warning: complete the todo list' + '\x1b[0m'
10 | }
11 |
12 | return null
13 | }
14 |
15 | module.exports = validate
16 |
--------------------------------------------------------------------------------
/util/analyzers/validators/zero-value.js:
--------------------------------------------------------------------------------
1 | const { isLib } = require('./lib')
2 | const { isMock } = require('./mock')
3 |
4 | const validate = async (code, _, name) => {
5 | if (isLib(name) || isMock(name)) {
6 | return null
7 | }
8 |
9 | const hasUint = code.toLowerCase().indexOf('uint') > -1
10 | const supressionMissing = code.toLowerCase().indexOf('@suppress-zero-value-check') === -1 && code.toLowerCase().indexOf('@custom:suppress-zero-value-check') === -1
11 | const hasCheck = code.toLowerCase().indexOf('> ') > -1 || code.toLowerCase().indexOf('>= ') > -1
12 |
13 | if (hasUint && supressionMissing && !hasCheck) {
14 | return '\x1b[31m' + '* Warning: Ensure that the uint value is not zero' + '\x1b[0m'
15 | }
16 |
17 | return null
18 | }
19 |
20 | module.exports = validate
21 |
--------------------------------------------------------------------------------
/util/attach/attach.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('hardhat')
2 |
3 | const attach = async (contractName, address, libraries) => {
4 | const contract = libraries ? await ethers.getContractFactory(contractName, libraries) : await ethers.getContractFactory(contractName)
5 | return contract.attach(address)
6 | }
7 |
8 | module.exports = { attach }
9 |
--------------------------------------------------------------------------------
/util/attach/index.js:
--------------------------------------------------------------------------------
1 | const attach = require('./attach')
2 | const protocol = require('./protocol')
3 |
4 | module.exports = { attach, protocol }
5 |
--------------------------------------------------------------------------------
/util/attach/protocol.js:
--------------------------------------------------------------------------------
1 | const { attach } = require('./attach')
2 |
3 | /**
4 | * Attaches protocol instance to a given address
5 | * @param {string} address
6 | * @param {Libraries} libraries
7 | * @returns {ethers.Contract}
8 | */
9 | const attacher = async (address, libraries) => {
10 | return attach('MockProtocol', address, {
11 | AccessControlLibV1: libraries.accessControlLibV1.address,
12 | BaseLibV1: libraries.baseLibV1.address,
13 | ProtoUtilV1: libraries.protoUtilV1.address,
14 | StoreKeyUtil: libraries.storeKeyUtil.address,
15 | ValidationLibV1: libraries.validationLibV1.address
16 | })
17 | }
18 |
19 | module.exports = { attach: attacher }
20 |
--------------------------------------------------------------------------------
/util/block-time.js:
--------------------------------------------------------------------------------
1 | const networks = {
2 | 1: {
3 | approximateBlockTime: 15
4 | },
5 | 3: {
6 | approximateBlockTime: 12
7 | },
8 | 42: {
9 | approximateBlockTime: 4
10 | },
11 | 97: {
12 | approximateBlockTime: 3
13 | },
14 | 80001: {
15 | approximateBlockTime: 3
16 | },
17 | 43113: {
18 | approximateBlockTime: 2
19 | },
20 | 84531: {
21 | approximateBlockTime: 2
22 | },
23 | 31337: {
24 | approximateBlockTime: 1
25 | },
26 | 31338: {
27 | approximateBlockTime: 1
28 | }
29 | }
30 |
31 | const minutesToBlocks = (chainId, minutes) => {
32 | try {
33 | const seconds = minutes * 60
34 | const { approximateBlockTime } = networks[chainId]
35 |
36 | return seconds / approximateBlockTime
37 | } catch (error) {
38 | console.error(error)
39 | }
40 |
41 | return networks[1]
42 | }
43 |
44 | const hoursToBlocks = (chainId, hours) => {
45 | const minutes = hours * 60
46 | return minutesToBlocks(chainId, minutes)
47 | }
48 |
49 | const daysToBlocks = (chainId, days) => {
50 | const hours = days * 24
51 | return hoursToBlocks(chainId, hours)
52 | }
53 |
54 | module.exports = { minutesToBlocks, hoursToBlocks, daysToBlocks }
55 |
--------------------------------------------------------------------------------
/util/block.js:
--------------------------------------------------------------------------------
1 | const hre = require('hardhat')
2 | const moment = require('moment')
3 |
4 | const getTimestamp = async () => {
5 | const { timestamp } = await hre.ethers.provider.getBlock('latest')
6 | return moment.unix(timestamp)
7 | }
8 |
9 | const mineBlocks = async (totalBlocks) => {
10 | while (totalBlocks > 0) {
11 | totalBlocks--
12 | await hre.network.provider.request({
13 | method: 'evm_mine',
14 | params: []
15 | })
16 | }
17 | }
18 |
19 | module.exports = { getTimestamp, mineBlocks }
20 |
--------------------------------------------------------------------------------
/util/composer/add-pools.js:
--------------------------------------------------------------------------------
1 | const { approve } = require('../contract-helper/erc20')
2 |
3 | const addPodStaking = async (intermediate, cache, info, contracts, provider) => {
4 | const { rewardToken } = info
5 |
6 | const { stakingPoolContract } = contracts
7 | await approve(rewardToken, stakingPoolContract.address, provider)
8 |
9 | await intermediate(cache, stakingPoolContract, 'addOrEditPool', info)
10 | }
11 |
12 | const addPools = async (intermediate, cache, pools, contracts, provider) => {
13 | console.log('Wait')
14 |
15 | for (const i in pools) {
16 | const pool = pools[i]
17 | console.log('Task %s:%s | %s', parseInt(i) + 1, pools.length, pool.name)
18 |
19 | await addPodStaking(intermediate, cache, pool, contracts, provider)
20 | }
21 | }
22 |
23 | module.exports = { addPools }
24 |
--------------------------------------------------------------------------------
/util/composer/external-protocols.js:
--------------------------------------------------------------------------------
1 | const hre = require('hardhat')
2 | const fakesComposer = require('./fakes')
3 | const { getNetworkInfo } = require('../network')
4 | const { zerox } = require('../helper')
5 |
6 | /**
7 | * Initializes all contracts
8 | * @return {Promise}
9 | */
10 | const getExternalProtocols = async (cache, tokens) => {
11 | const network = await getNetworkInfo()
12 |
13 | let router = network?.uniswapV2Like?.addresses?.router
14 | let factory = network?.uniswapV2Like?.addresses?.factory
15 | let priceOracle = network?.uniswapV2Like?.addresses?.npmPriceOracle
16 | let aaveLendingPool = network?.aave?.addresses?.lendingPool
17 | let compoundStablecoinDelegator = network?.compound?.stablecoin?.delegator
18 |
19 | if (hre.network.name === 'hardhat') {
20 | const fakes = await fakesComposer.deployAll(cache, tokens)
21 |
22 | if (!router) {
23 | router = fakes.router.address
24 | }
25 |
26 | if (!factory) {
27 | factory = fakes.factory.address
28 | }
29 |
30 | if (!aaveLendingPool) {
31 | aaveLendingPool = fakes.aave.lendingPool.address
32 | }
33 |
34 | if (!compoundStablecoinDelegator) {
35 | compoundStablecoinDelegator = fakes.compound.stablecoinDelegator.address
36 | }
37 | }
38 |
39 | if (!priceOracle) {
40 | priceOracle = zerox
41 | }
42 |
43 | return {
44 | router,
45 | factory,
46 | priceOracle,
47 | aaveLendingPool,
48 | compoundStablecoinDelegator
49 | }
50 | }
51 |
52 | module.exports = { getExternalProtocols }
53 |
--------------------------------------------------------------------------------
/util/composer/fakes.js:
--------------------------------------------------------------------------------
1 | const { deployer } = require('..')
2 |
3 | const deployAll = async (cache, tokens) => {
4 | const { stablecoin, cStablecoin, aToken } = tokens
5 |
6 | const router = await deployer.deploy(cache, 'FakeUniswapV2RouterLike')
7 | const pair = await deployer.deploy(cache, 'FakeUniswapV2PairLike', '0x0000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000002')
8 | const factory = await deployer.deploy(cache, 'FakeUniswapV2FactoryLike', pair.address)
9 | const lendingPool = await deployer.deploy(cache, 'FakeAaveLendingPool', aToken.address)
10 | const stablecoinDelegator = await deployer.deploy(cache, 'FakeCompoundStablecoinDelegator', stablecoin.address, cStablecoin.address)
11 | const priceOracle = await deployer.deploy(cache, 'FakePriceOracle')
12 |
13 | await stablecoin.addMinter(lendingPool.address, true)
14 | await aToken.addMinter(lendingPool.address, true)
15 |
16 | await stablecoin.addMinter(stablecoinDelegator.address, true)
17 | await cStablecoin.addMinter(stablecoinDelegator.address, true)
18 |
19 | return { router, pair, factory, priceOracle, aave: { lendingPool }, compound: { stablecoinDelegator } }
20 | }
21 |
22 | module.exports = { deployAll }
23 |
--------------------------------------------------------------------------------
/util/composer/grant-roles.js:
--------------------------------------------------------------------------------
1 | const hre = require('hardhat')
2 | const { getNetworkInfo } = require('../network')
3 | const { ACCESS_CONTROL } = require('../../util/key')
4 | const { key } = require('..')
5 |
6 | const grantRoles = async (intermediate, cache, { protocol, cover, policy }) => {
7 | const [owner] = await hre.ethers.getSigners()
8 | const network = await getNetworkInfo()
9 |
10 | const payload = [{
11 | account: owner.address,
12 | roles: [
13 | ACCESS_CONTROL.COVER_MANAGER,
14 | ACCESS_CONTROL.UPGRADE_AGENT,
15 | ACCESS_CONTROL.GOVERNANCE_ADMIN
16 | ]
17 | }]
18 |
19 | if (network.mainnet === false) {
20 | payload[payload.length - 1].roles.push(ACCESS_CONTROL.LIQUIDITY_MANAGER)
21 | }
22 |
23 | if (network?.knownAccounts) {
24 | payload.push(...network.knownAccounts)
25 | }
26 |
27 | payload.push({
28 | account: cover.address,
29 | roles: [key.ACCESS_CONTROL.UPGRADE_AGENT]
30 | },
31 | {
32 | account: policy.address,
33 | roles: [key.ACCESS_CONTROL.UPGRADE_AGENT]
34 | },
35 | {
36 | account: protocol.address,
37 | roles: [key.ACCESS_CONTROL.UPGRADE_AGENT]
38 | })
39 |
40 | await intermediate(cache, protocol, 'grantRoles', payload)
41 | }
42 |
43 | module.exports = { grantRoles }
44 |
--------------------------------------------------------------------------------
/util/composer/index.js:
--------------------------------------------------------------------------------
1 | const store = require('./store')
2 | const libs = require('./libs')
3 | const token = require('./token')
4 | const vault = require('./vault')
5 | const initializer = require('./initializer')
6 |
7 | module.exports = { initializer, store, libs, token, vault }
8 |
--------------------------------------------------------------------------------
/util/composer/store.js:
--------------------------------------------------------------------------------
1 | const { deployer } = require('..')
2 |
3 | const deploy = async (cache) => {
4 | return deployer.deploy(cache, 'Store')
5 | }
6 |
7 | module.exports = { deploy }
8 |
--------------------------------------------------------------------------------
/util/composer/vault.js:
--------------------------------------------------------------------------------
1 | const { storeUtil } = require('../../util')
2 |
3 | /**
4 | * Gets the vault from store
5 | * @param {Contracts} contracts All contracts
6 | * @param {string} coverKey The cover Key
7 | * @returns {any} Returns the vault contract
8 | */
9 | const getVault = async (contracts, coverKey) => {
10 | const vaultAddress = await storeUtil.getVaultAddress(contracts.store, coverKey)
11 |
12 | const Vault = await ethers.getContractFactory('Vault', {
13 | libraries: {
14 | AccessControlLibV1: contracts.libs.accessControlLibV1.address,
15 | BaseLibV1: contracts.libs.baseLibV1.address,
16 | NTransferUtilV2: contracts.libs.transferLib.address,
17 | ProtoUtilV1: contracts.libs.protoUtilV1.address,
18 | RegistryLibV1: contracts.libs.registryLibV1.address,
19 | ValidationLibV1: contracts.libs.validationLibV1.address
20 | }
21 | })
22 |
23 | return Vault.attach(vaultAddress)
24 | }
25 |
26 | module.exports = { getVault }
27 |
--------------------------------------------------------------------------------
/util/contract-helper/erc20.js:
--------------------------------------------------------------------------------
1 | const { ethers, network } = require('hardhat')
2 | const erc20abi = require('../../abis/IERC20Detailed.json')
3 |
4 | const getInstance = async (at, signer) => {
5 | const [owner] = await ethers.getSigners()
6 | return new ethers.Contract(at, erc20abi, signer || owner)
7 | }
8 |
9 | const approve = async (tokenAddress, spender, account, amount = ethers.constants.MaxUint256) => {
10 | const erc20 = await getInstance(tokenAddress, account)
11 |
12 | if (network.name !== 'hardhat') {
13 | const allowance = await erc20.allowance(account.address, spender)
14 | const symbol = await erc20.symbol()
15 |
16 | if (allowance.gte(amount)) {
17 | console.info('Spender %s already approved to spend %s from account %s', spender, symbol, account.address)
18 | return
19 | }
20 | }
21 |
22 | const tx = await erc20.connect(account).approve(spender, amount)
23 | await tx.wait()
24 | }
25 |
26 | module.exports = { getInstance, approve }
27 |
--------------------------------------------------------------------------------
/util/contract-helper/faucet.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('hardhat')
2 | const { ether } = require('../helper')
3 |
4 | const request = async (token, amount) => {
5 | const [owner] = await ethers.getSigners()
6 |
7 | const balance = await token.balanceOf(owner.address)
8 |
9 | if (balance.gte(amount || '0')) {
10 | return
11 | }
12 |
13 | const contract = await new ethers.Contract(token.address, ['function mint(uint256) external'], owner)
14 | console.info('Requesting tokens')
15 |
16 | const tx = await contract.connect(owner).mint(amount || ether(1_000_000))
17 | await tx.wait()
18 | }
19 |
20 | module.exports = { request }
21 |
--------------------------------------------------------------------------------
/util/contract-helper/uniswap.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('hardhat')
2 | const routerAbi = require('../../abis/IUniswapV2RouterLike.json')
3 | const factoryAbi = require('../../abis/IUniswapV2FactoryLike.json')
4 | const pairAbi = require('../../abis/IUniswapV2PairLike.json')
5 | const { helper } = require('..')
6 |
7 | const getRouter = async (routerAt, signer) => {
8 | const [owner] = await ethers.getSigners()
9 | return new ethers.Contract(routerAt, routerAbi, signer || owner)
10 | }
11 |
12 | const getFactory = async (factoryAt, signer) => {
13 | const [owner] = await ethers.getSigners()
14 | return new ethers.Contract(factoryAt, factoryAbi, signer || owner)
15 | }
16 |
17 | const getPair = async (pairAt, signer) => {
18 | if (pairAbi === helper.zerox) {
19 | return helper.zerox
20 | }
21 |
22 | const [owner] = await ethers.getSigners()
23 | return new ethers.Contract(pairAt, pairAbi, signer || owner)
24 | }
25 |
26 | module.exports = { getRouter, getFactory, getPair }
27 |
--------------------------------------------------------------------------------
/util/cxToken.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Gets cxToken from an address
3 | * @param {string} at Address where your cxToken is deployed
4 | * @param {Libraries} libraries The deployed libraries
5 | */
6 | const atAddress = async (at, libraries) => {
7 | const cxToken = await ethers.getContractFactory('cxToken', {
8 | libraries: {
9 | AccessControlLibV1: libraries.accessControlLibV1.address,
10 | BaseLibV1: libraries.baseLibV1.address,
11 | CoverUtilV1: libraries.coverUtilV1.address,
12 | GovernanceUtilV1: libraries.governanceUtilV1.address,
13 | PolicyHelperV1: libraries.policyHelperV1.address,
14 | ProtoUtilV1: libraries.protoUtilV1.address,
15 | StoreKeyUtil: libraries.storeKeyUtil.address,
16 | ValidationLibV1: libraries.validationLibV1.address
17 |
18 | }
19 | })
20 |
21 | return cxToken.attach(at)
22 | }
23 |
24 | module.exports = { atAddress }
25 |
--------------------------------------------------------------------------------
/util/demo-data/add-liquidity.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('hardhat')
2 | const { covers } = require('../../examples')
3 | const composer = require('../composer')
4 | const { ether, getRandomNumber, weiAsToken, STABLECOIN_DECIMALS } = require('../helper')
5 | const { approve } = require('../contract-helper/erc20')
6 | const { key } = require('..')
7 | const PRECISION = STABLECOIN_DECIMALS
8 |
9 | const add = async (coverKey, payload) => {
10 | const [lp] = await ethers.getSigners() // eslint-disable-line
11 | const amount = ether(getRandomNumber(1_250_000, 5_000_000), PRECISION)
12 | const npmStakeToAdd = ether(getRandomNumber(1000, 125_000))
13 |
14 | const { tokens } = payload
15 | const vault = await composer.vault.getVault(payload, coverKey)
16 |
17 | console.info('%s %s %s', vault.address, tokens.stablecoin.address, tokens.npm.address)
18 |
19 | await approve(tokens.stablecoin.address, vault.address, lp, ethers.constants.MaxUint256)
20 | await approve(tokens.npm.address, vault.address, lp, ethers.constants.MaxUint256)
21 |
22 | console.info('Adding %s to the vault. Stake: %s. From: %s', weiAsToken(amount, 'USDC', PRECISION), weiAsToken(npmStakeToAdd, 'NPM'), lp.address)
23 |
24 | await vault.addLiquidity({
25 | coverKey,
26 | amount,
27 | npmStakeToAdd,
28 | referralCode: key.toBytes32('')
29 | })
30 |
31 | console.info('Added %s to the vault. Stake: %s', weiAsToken(amount, 'USDC', PRECISION), weiAsToken(npmStakeToAdd, 'NPM'))
32 | }
33 |
34 | const addLiquidity = async (payload) => {
35 | for (const i in covers) {
36 | const { coverKey, coverName } = covers[i]
37 |
38 | console.info('Adding liquidity to %s', coverName)
39 | await add(coverKey, payload)
40 | }
41 | }
42 |
43 | module.exports = { addLiquidity }
44 |
--------------------------------------------------------------------------------
/util/demo-data/add-reassurance.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('hardhat')
2 | const { covers } = require('../../examples')
3 | const { ether, getRandomNumber, weiAsToken, STABLECOIN_DECIMALS } = require('../helper')
4 | const { approve } = require('../contract-helper/erc20')
5 | const faucet = require('../contract-helper/faucet')
6 | const PRECISION = STABLECOIN_DECIMALS
7 |
8 | const add = async (coverKey, payload) => {
9 | const [owner] = await ethers.getSigners()
10 | const amount = ether(getRandomNumber(250_000, 5_000_000), PRECISION)
11 |
12 | const { tokens, reassuranceContract } = payload
13 |
14 | await faucet.request(tokens.stablecoin, amount)
15 |
16 | await approve(tokens.stablecoin.address, reassuranceContract.address, owner, ethers.constants.MaxUint256)
17 |
18 | await reassuranceContract.connect(owner).addReassurance(coverKey, owner.address, amount)
19 |
20 | console.info('Added %s to the reassurance vault.', weiAsToken(amount, 'USDC', PRECISION))
21 | }
22 |
23 | const addReassurance = async (payload) => {
24 | for (const i in covers) {
25 | const { coverKey, coverName } = covers[i]
26 |
27 | console.info('Adding reassurance to %s', coverName)
28 | await add(coverKey, payload)
29 | }
30 | }
31 |
32 | module.exports = { addReassurance }
33 |
--------------------------------------------------------------------------------
/util/demo-data/index.js:
--------------------------------------------------------------------------------
1 | const { addLiquidity } = require('./add-liquidity')
2 | const { addReassurance } = require('./add-reassurance')
3 |
4 | const create = async (payload) => {
5 | console.info('Creating demo data')
6 | await addLiquidity(payload)
7 | await addReassurance(payload)
8 | }
9 |
10 | module.exports = { create }
11 |
--------------------------------------------------------------------------------
/util/demo-data/purchase-policy.js:
--------------------------------------------------------------------------------
1 | const { covers } = require('../../examples')
2 | const composer = require('../composer')
3 | const { ether, getRandomNumber, weiAsToken, STABLECOIN_DECIMALS } = require('../helper')
4 | const { toBytes32 } = require('../key')
5 | const { approve } = require('../contract-helper/erc20')
6 | const PRECISION = STABLECOIN_DECIMALS
7 |
8 | const add = async (coverKey, payload) => {
9 | const [lp] = await ethers.getSigners() // eslint-disable-line
10 | const amount = ether(getRandomNumber(250_000, 5_000_000), PRECISION)
11 | const stake = ether(getRandomNumber(1000, 125_000))
12 |
13 | const { stablecoin, npm } = payload
14 | const vault = await composer.vault.getVault(payload, coverKey)
15 |
16 | await stablecoin.mint(amount)
17 | await npm.mint(stake)
18 |
19 | await approve(stablecoin.address, vault.address, lp, amount)
20 | await approve(npm.address, vault.address, lp, stake)
21 |
22 | await vault.connect(lp).addLiquidity({
23 | coverKey,
24 | amount,
25 | npmStakeToAdd: stake,
26 | referralCode: toBytes32('')
27 | })
28 |
29 | console.info('Added %s to the vault. Stake: %s', weiAsToken(amount, 'USDC'), weiAsToken(stake, 'NPM'))
30 | }
31 |
32 | const addLiquidity = async (payload) => {
33 | for (const i in covers) {
34 | const { key, coverName } = covers[i]
35 |
36 | console.info('Adding liquidity to %s', coverName)
37 | await add(key, payload)
38 | }
39 | }
40 |
41 | module.exports = { addLiquidity }
42 |
--------------------------------------------------------------------------------
/util/events/all.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const io = require('../io')
3 |
4 | const getFileList = async () => io.findFiles('json', path.join(process.cwd(), 'abis'))
5 | const ignored = ['Approval', 'Transfer']
6 | const divider = '-'.repeat(128)
7 |
8 | const getEvents = async (file) => {
9 | const contents = await io.readFile(file)
10 | const parsed = JSON.parse(contents)
11 | const events = parsed.filter(x => x.type === 'event')
12 |
13 | const result = [`${file}`, divider]
14 |
15 | const candidates = []
16 |
17 | for (const event of events) {
18 | if (ignored.indexOf(event.name) > -1) {
19 | continue
20 | }
21 |
22 | const args = event.inputs
23 | .filter(x => ['Approval', 'Transfer'].indexOf(x.name) === -1)
24 | .map(x => {
25 | const { indexed, type, name } = x
26 |
27 | return `${type}${indexed ? ' indexed' : ''} ${name}`
28 | }).join(', ')
29 |
30 | candidates.push(`event ${event.name}(${args});`)
31 | }
32 |
33 | if (candidates.length === 0) {
34 | return ''
35 | }
36 |
37 | result.push('```\n' + candidates.join('\n') + '\n```')
38 |
39 | result.push('')
40 | return result.join('\n')
41 | }
42 |
43 | const start = async () => {
44 | const events = []
45 | const abis = await getFileList()
46 |
47 | if (!abis.length) {
48 | console.error(new Error('Please first export the ABIs'))
49 | return
50 | }
51 |
52 | for (const abi of abis) {
53 | events.push(await getEvents(abi))
54 | }
55 |
56 | console.info(events.filter(x => !!x).join('\n'))
57 | }
58 |
59 | start()
60 |
--------------------------------------------------------------------------------
/util/events/index.js:
--------------------------------------------------------------------------------
1 | const all = require('./all')
2 |
3 | module.exports = {
4 | all
5 | }
6 |
--------------------------------------------------------------------------------
/util/events/table.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const io = require('../io')
3 |
4 | const getFileList = async () => io.findFiles('json', path.join(process.cwd(), 'abis'))
5 | const ignored = ['Approval', 'Transfer']
6 |
7 | const getEvents = async (file) => {
8 | const contents = await io.readFile(file)
9 | const parsed = JSON.parse(contents)
10 | const events = parsed.filter(x => x.type === 'event')
11 |
12 | const candidates = []
13 |
14 | for (const event of events) {
15 | const { name } = event
16 | if (ignored.indexOf(name) > -1) {
17 | continue
18 | }
19 |
20 | candidates.push(`${file.split('/').pop()} | ${name} | |`)
21 | }
22 |
23 | if (candidates.length === 0) {
24 | return
25 | }
26 |
27 | console.log(candidates.join('\n'))
28 | }
29 |
30 | const start = async () => {
31 | const abis = await getFileList()
32 |
33 | if (!abis.length) {
34 | console.error(new Error('Please first export the ABIs'))
35 | return
36 | }
37 |
38 | console.log('| Contract | Events | Roles |')
39 | console.log('| -------- | ------ | ------- |')
40 |
41 | for (const abi of abis) {
42 | await getEvents(abi)
43 | }
44 | }
45 |
46 | start()
47 |
--------------------------------------------------------------------------------
/util/extract/abis/index.js:
--------------------------------------------------------------------------------
1 | const io = require('../../io')
2 | const path = require('path')
3 | const root = path.join('artifacts', 'contracts', 'interfaces')
4 |
5 | const getFiles = async () => {
6 | const hasFiles = await io.exists(root)
7 |
8 | if (!hasFiles) {
9 | const command = '\x1b[36m' + 'npx hardhat compile' + '\x1b[0m'
10 | console.log(`Please generate artifacts using: ${command}`)
11 | return
12 | }
13 |
14 | const files = await io.findFiles('json', root)
15 | const all = files.map(x => `${x.replace('.dbg', '')}`)
16 |
17 | all.push('./artifacts/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol/IERC20.json')
18 | all.push('./artifacts/contracts/dependencies/aave/IAaveV2LendingPoolLike.sol/IAaveV2LendingPoolLike.json')
19 | all.push('./artifacts/contracts/dependencies/compound/ICompoundERC20DelegatorLike.sol/ICompoundERC20DelegatorLike.json')
20 | all.push('./artifacts/contracts/dependencies/uniswap-v2/IUniswapV2FactoryLike.sol/IUniswapV2FactoryLike.json')
21 | all.push('./artifacts/contracts/dependencies/uniswap-v2/IUniswapV2PairLike.sol/IUniswapV2PairLike.json')
22 | all.push('./artifacts/contracts/dependencies/uniswap-v2/IUniswapV2RouterLike.sol/IUniswapV2RouterLike.json')
23 |
24 | return [...new Set(all)]
25 | }
26 |
27 | const createAbi = async (file) => {
28 | const destination = path.join(process.cwd(), 'abis', file.split('/').pop())
29 |
30 | if (!(await io.exists(file))) {
31 | return
32 | }
33 |
34 | const contents = await io.readFile(file)
35 | const artifact = JSON.parse(contents)
36 |
37 | await io.ensureFile(destination, JSON.stringify(artifact.abi, null, 2))
38 | }
39 |
40 | const extract = async () => {
41 | const files = await getFiles()
42 |
43 | for (const i in files) {
44 | await createAbi(files[i])
45 | }
46 | }
47 |
48 | extract()
49 |
--------------------------------------------------------------------------------
/util/extract/genabi.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs').promises
3 | const {
4 | FormatTypes,
5 | Interface
6 | } = require('@ethersproject/abi')
7 |
8 | const { exists, findFiles, writeFile, ensureFile } = require('../io')
9 |
10 | const srcAbiFolder = path.resolve('.', process.argv[2])
11 | const targetFile = path.resolve('.', process.argv[3])
12 |
13 | if (!exists(srcAbiFolder)) {
14 | throw Error('Invalid ABI directory')
15 | }
16 |
17 | const generateFileContents = async () => {
18 | const files = await findFiles('json', srcAbiFolder)
19 |
20 | if (files.length === 0) {
21 | throw Error('No ABIs found')
22 | }
23 |
24 | const contents = []
25 | const exportedVariables = []
26 |
27 | for (let i = 0; i < files.length; i++) {
28 | const file = files[i]
29 |
30 | const variable = path.parse(file).name
31 | const abi = await fs.readFile(file)
32 | try {
33 | const iface = new Interface(abi.toString())
34 |
35 | // abi constant declaration
36 | contents.push(
37 | `const ${variable} = ${JSON.stringify(iface.format(FormatTypes.full), null, 2)}`
38 | )
39 | } catch (error) {
40 | console.error('Invalid ABI %s', file, error)
41 | }
42 |
43 | exportedVariables.push(variable)
44 | }
45 |
46 | // export statement
47 | contents.push(`export {\n ${exportedVariables.join(',\n ')}\n}`)
48 |
49 | return contents.join('\n\n')
50 | }
51 |
52 | async function main () {
53 | console.log('Generating abi:js from %s', srcAbiFolder)
54 | const contents = await generateFileContents()
55 |
56 | await ensureFile(targetFile)
57 | await writeFile(targetFile, contents)
58 | console.log('Generated: %s', targetFile)
59 | }
60 |
61 | main()
62 |
--------------------------------------------------------------------------------
/util/extract/keys/code-generator-as.js:
--------------------------------------------------------------------------------
1 | const Enumerable = require('node-enumerable')
2 |
3 | const generate = async (all) => {
4 | Enumerable.from(all)
5 | .orderBy(x => x.prefix)
6 | .thenBy(x => x.key)
7 | .each(c => {
8 | const comment = c.comment ? ` // ${c.comment}` : ''
9 | const value = c.value === '0x00' ? 'toBytes32("")' : `toBytes32("${c.value}")`
10 | console.info(`export const ${c.prefix}${c.key} = ${value};${comment}`)
11 | })
12 | }
13 |
14 | module.exports = { generate }
15 |
--------------------------------------------------------------------------------
/util/extract/keys/code-generator.js:
--------------------------------------------------------------------------------
1 | const Enumerable = require('node-enumerable')
2 |
3 | const generate = async (groupKey, group) => {
4 | const prefixes = Enumerable.from(group).select(x => x.prefix).distinct().toArray()
5 |
6 | const builder = []
7 | builder.push(`const ${groupKey} = {`)
8 |
9 | Enumerable.from(group).groupBy(x => x.prefix).each(item => {
10 | const candidates = item.toArray()
11 |
12 | if (prefixes.length === 1) {
13 | const code = candidates.map(x => ` ${x.key}: toBytes32('${x.value === '0x00' ? '' : x.value}'),`)
14 | builder.push(...code)
15 | } else {
16 | builder.push(` ${item.key.slice(0, -1)}: {`)
17 | const code = candidates.map(x => ` ${x.key}: toBytes32('${x.value === '0x00' ? '' : x.value}'),`)
18 | builder.push(...code)
19 | builder.push(' },')
20 | }
21 | })
22 |
23 | builder.push('}\n\n')
24 | console.log(builder.join('\n'))
25 | }
26 |
27 | module.exports = { generate }
28 |
--------------------------------------------------------------------------------
/util/extract/keys/index.js:
--------------------------------------------------------------------------------
1 | const Enumerable = require('node-enumerable')
2 | const files = require('./requirement')
3 | const codegen = require('./code-generator')
4 | const codegenAs = require('./code-generator-as')
5 | const processor = require('./processor')
6 | const template = require('./template')
7 | const [, , type] = process.argv
8 |
9 | const start = async () => {
10 | const candidates = []
11 | const mode = type && type.replace('--', '')
12 | const { pre, post } = template.get(mode)
13 |
14 | console.log(pre)
15 | console.log('\n')
16 |
17 | for (const i in files) {
18 | const result = await processor.process(files[i])
19 | candidates.push(...result)
20 | }
21 |
22 | if (mode === 'as') {
23 | await codegenAs.generate(candidates)
24 | return
25 | }
26 |
27 | Enumerable.from(candidates)
28 | .groupBy(x => x.scope)
29 | .each(async (scope) => codegen.generate(scope.key, scope.toArray()))
30 |
31 | const scopes = Enumerable.from(candidates).select(x => x.scope).distinct().toArray().join(', ')
32 |
33 | console.log(post.replace('{{scopes}}', scopes))
34 | }
35 |
36 | start()
37 |
--------------------------------------------------------------------------------
/util/extract/keys/processor.js:
--------------------------------------------------------------------------------
1 | const io = require('../../io')
2 |
3 | const extractPair = (match, scope, prefix, type) => {
4 | const parts = match.replace('bytes32 public constant ', '').split('=')
5 | let [key, contents] = parts
6 |
7 | let [value, comment] = contents.trim().split(';')
8 |
9 | key = key.trim().replace(prefix, '')
10 | value = value.replace(/"/g, '').trim()
11 | comment = (comment || '').replace('//', '').trim()
12 |
13 | return { scope, prefix, key, value, comment, type }
14 | }
15 |
16 | const process = async (file) => {
17 | const { type, scope, prefix, expression, src } = file
18 | const contents = await io.readFile(src)
19 | const matches = contents.match(expression)
20 |
21 | return matches.map(x => extractPair(x.trim(), scope, prefix, type))
22 | }
23 |
24 | module.exports = { process }
25 |
--------------------------------------------------------------------------------
/util/extract/keys/requirement.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | scope: 'ACCESS_CONTROL',
4 | type: 'role',
5 | prefix: 'NS_ROLES_',
6 | expression: /.*constant NS_ROLES_.*\n/g,
7 | src: './contracts/Libraries/AccessControlLibV1.sol'
8 | },
9 | {
10 | scope: 'BOND',
11 | type: 'bond',
12 | prefix: 'NS_BOND_',
13 | expression: /.*constant NS_BOND_.*\n/g,
14 | src: './contracts/Libraries/BondPoolLibV1.sol'
15 | },
16 | {
17 | scope: 'PROTOCOL',
18 | type: 'cns',
19 | prefix: 'CNS_',
20 | expression: /.*constant CNS_.*\n/g,
21 | src: './contracts/Libraries/ProtoUtilV1.sol'
22 | },
23 | {
24 | scope: 'PROTOCOL',
25 | type: 'ns',
26 | prefix: 'NS_',
27 | expression: /.*constant NS_.*\n/g,
28 | src: './contracts/Libraries/ProtoUtilV1.sol'
29 | },
30 | {
31 | scope: 'PROTOCOL',
32 | type: 'cname',
33 | prefix: 'CNAME_',
34 | expression: /.*constant CNAME_.*\n/g,
35 | src: './contracts/Libraries/ProtoUtilV1.sol'
36 | },
37 | {
38 | scope: 'STAKING',
39 | type: 'staking:pool',
40 | prefix: 'NS_POOL_',
41 | expression: /.*constant NS_POOL_.*\n/g,
42 | src: './contracts/Libraries/StakingPoolCoreLibV1.sol'
43 | }
44 | ]
45 |
--------------------------------------------------------------------------------
/util/extract/keys/template-as.js:
--------------------------------------------------------------------------------
1 | const pre = `import { ByteArray } from "@graphprotocol/graph-ts";
2 |
3 | const toBytes32 = (x: string): ByteArray => ByteArray.fromUTF8(x);`
4 |
5 | const post = ''
6 |
7 | module.exports = { pre, post }
8 |
--------------------------------------------------------------------------------
/util/extract/keys/template-js.js:
--------------------------------------------------------------------------------
1 | const pre = `const ethers = require('ethers')
2 |
3 | const encodeKey = (x) => ethers.utils.solidityKeccak256(['bytes32'], [toBytes32(x)])
4 | const encodeKeys = (x, y) => ethers.utils.solidityKeccak256(x, y)
5 | const toBytes32 = (x) => ethers.utils.formatBytes32String(x)
6 | const getCoverContractKey = (namespace, coverKey) => encodeKeys(['bytes32', 'bytes32'], [toBytes32(namespace), coverKey])
7 | const qualifyBytes32 = (k) => encodeKeys(['bytes32', 'bytes32'], [PROTOCOL.NS.CONTRACTS, k])
8 | const qualify = (k) => encodeKeys(['bytes32', 'address'], [PROTOCOL.NS.CONTRACTS, k])
9 | const qualifyMember = (k) => encodeKeys(['bytes32', 'address'], [PROTOCOL.NS.MEMBERS, k])`
10 |
11 | const post = `module.exports = {
12 | encodeKey,
13 | encodeKeys,
14 | toBytes32,
15 | getCoverContractKey,
16 | qualify,
17 | qualifyMember,
18 | qualifyBytes32,
19 | {{scopes}}
20 | }`
21 |
22 | module.exports = { pre, post }
23 |
--------------------------------------------------------------------------------
/util/extract/keys/template-ts.js:
--------------------------------------------------------------------------------
1 | const pre = `import { keccak256 as solidityKeccak256 } from '@ethersproject/solidity'
2 | import { formatBytes32String } from '@ethersproject/strings'
3 |
4 | const encodeKey = (x: string): string => solidityKeccak256(['bytes32'], [x])
5 | const encodeKeys = (x: string[], y: string[]): string => solidityKeccak256(x, y)
6 | const toBytes32 = (x: string): string => formatBytes32String(x)
7 | const getCoverContractKey = (namespace: string, coverKey: string): string => encodeKeys(['bytes32', 'bytes32'], [namespace, coverKey])
8 | const qualifyBytes32 = (k: string): string => encodeKeys(['bytes32', 'bytes32'], [PROTOCOL.NS.CONTRACTS, k])
9 | const qualify = (k: string): string => encodeKeys(['bytes32', 'address'], [PROTOCOL.NS.CONTRACTS, k])
10 | const qualifyMember = (k: string): string => encodeKeys(['bytes32', 'address'], [PROTOCOL.NS.MEMBERS, k])`
11 |
12 | const post = `export {
13 | encodeKey,
14 | encodeKeys,
15 | toBytes32,
16 | getCoverContractKey,
17 | qualify,
18 | qualifyMember,
19 | qualifyBytes32,
20 | {{scopes}}
21 | }`
22 |
23 | module.exports = { pre, post }
24 |
--------------------------------------------------------------------------------
/util/extract/keys/template.js:
--------------------------------------------------------------------------------
1 | const tas = require('./template-as')
2 | const tjs = require('./template-js')
3 | const tts = require('./template-ts')
4 |
5 | const get = (type) => {
6 | if (type === 'ts') {
7 | return tts
8 | }
9 |
10 | if (type === 'as') {
11 | return tas
12 | }
13 |
14 | return tjs
15 | }
16 |
17 | module.exports = { get }
18 |
--------------------------------------------------------------------------------
/util/file-cache/contract.js:
--------------------------------------------------------------------------------
1 | const { getData } = require('./data')
2 |
3 | const getContract = async (file, id, contractName) => {
4 | const data = await getData(file)
5 | const { deployments } = data[id]
6 |
7 | for (const prop in deployments) {
8 | const contract = deployments[prop]
9 |
10 | const found = contract.contractName === contractName
11 |
12 | if (found) {
13 | return contract.address
14 | }
15 | }
16 |
17 | return null
18 | }
19 |
20 | module.exports = { getContract }
21 |
--------------------------------------------------------------------------------
/util/file-cache/data.js:
--------------------------------------------------------------------------------
1 | const io = require('../io')
2 |
3 | const getData = async (file) => {
4 | const contents = await io.readFile(file)
5 | return JSON.parse(contents)
6 | }
7 |
8 | module.exports = { getData }
9 |
--------------------------------------------------------------------------------
/util/file-cache/index.js:
--------------------------------------------------------------------------------
1 | const hre = require('hardhat')
2 | const path = require('path')
3 | const io = require('../io')
4 | const { getData } = require('./data')
5 | const { getContract } = require('./contract')
6 | const { getContracts } = require('./addresses')
7 | const { addUpgrade } = require('./upgrade')
8 |
9 | const from = async (id) => {
10 | const network = hre.network.name
11 |
12 | const file = path.join(process.cwd(), '.deployments', `${network}.json`)
13 |
14 | await io.ensureFile(file, '{}')
15 |
16 | return {
17 | file,
18 | getData: () => getData(file),
19 | addUpgrade: (upgrade) => addUpgrade(file, id, upgrade),
20 | getContract: (contractName) => getContract(file, id, contractName),
21 | getContracts: () => getContracts(file, id),
22 | id
23 | }
24 | }
25 |
26 | module.exports = { from }
27 |
--------------------------------------------------------------------------------
/util/file-cache/upgrade.js:
--------------------------------------------------------------------------------
1 | const io = require('../io')
2 | const { getData } = require('./data')
3 |
4 | const addUpgrade = async (file, id, upgrade) => {
5 | const data = await getData(file)
6 |
7 | if (!data[id].upgrades) {
8 | data[id].upgrades = []
9 | }
10 |
11 | data[id].upgrades.push(upgrade)
12 |
13 | await io.writeFile(file, JSON.stringify(data, null, 2))
14 | }
15 |
16 | module.exports = { addUpgrade }
17 |
--------------------------------------------------------------------------------
/util/index.js:
--------------------------------------------------------------------------------
1 | const cxToken = require('./cxToken')
2 | const helper = require('./helper')
3 | const deployer = require('./deployer')
4 | const key = require('./key')
5 | const storeUtil = require('./store-util')
6 | const ipfs = require('./ipfs')
7 | const io = require('./io')
8 | const fileCache = require('./file-cache')
9 | const intermediate = require('./intermediate')
10 | const sample = require('./sample')
11 | const typedefs = require('./typedefs')
12 |
13 | module.exports = { cxToken, helper, deployer, key, storeUtil, ipfs, sample, io, intermediate, fileCache, typedefs }
14 |
--------------------------------------------------------------------------------
/util/intermediate.js:
--------------------------------------------------------------------------------
1 | const io = require('./io')
2 |
3 | module.exports = async (cache, contract, action, ...args) => {
4 | const key = [action, contract.address, contract.interface.encodeFunctionData(action, [...args])].join('.')
5 |
6 | const persisted = await io.fetchValue(cache, key)
7 |
8 | if (persisted) {
9 | global.log && console.log('[skip] %s(%s) to %s was found on the tx %s', action, JSON.stringify(args), contract.address, persisted)
10 | return
11 | }
12 |
13 | global.log && console.log('[tx] %s(%s) to %s', action, JSON.stringify(args), contract.address)
14 |
15 | const tx = await contract[action](...args)
16 | await tx.wait()
17 | await io.cacheValue(cache, key, tx.hash)
18 | }
19 |
--------------------------------------------------------------------------------
/util/ipfs.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios')
2 |
3 | const write = async (contents) => {
4 | const { data } = await axios.put(process.env.NPM_IPFS_API_URL, contents)
5 | const { hash } = data
6 |
7 | return hash
8 | }
9 |
10 | module.exports = { write }
11 |
--------------------------------------------------------------------------------
/util/network.js:
--------------------------------------------------------------------------------
1 | const hre = require('hardhat')
2 | const network = require('../scripts/config/network')
3 |
4 | const getNetworkInfo = async () => {
5 | return network[hre.network.config.chainId]
6 | }
7 |
8 | module.exports = { getNetworkInfo }
9 |
--------------------------------------------------------------------------------
/util/store-util.js:
--------------------------------------------------------------------------------
1 | const key = require('./key')
2 |
3 | const getStoreAddressCustom = async (store, namespace, coverKey) => store.getAddress(key.getCoverContractKey(namespace, coverKey))
4 | const getVaultAddress = async (store, coverKey) => store.getAddress(key.encodeKeys(['bytes32', 'bytes32', 'bytes32'], [key.PROTOCOL.NS.CONTRACTS, key.PROTOCOL.CNS.COVER_VAULT, coverKey]))
5 |
6 | module.exports = {
7 | getStoreAddressCustom,
8 | getVaultAddress
9 | }
10 |
--------------------------------------------------------------------------------
/util/wallet.js:
--------------------------------------------------------------------------------
1 | const ethers = require('ethers')
2 |
3 | const toWalletAddress = (privateKey) => {
4 | const wallet = new ethers.Wallet(privateKey)
5 | return wallet.address
6 | }
7 |
8 | module.exports = {
9 | toWalletAddress
10 | }
11 |
--------------------------------------------------------------------------------