SSRP - Smart Contract Audit Report

Summary

SSRP Audit Report Uno Re is building a set of smart contracts to faciliate a single-sided reinsurance platform with opportunities to stake funds and earn rewards.

We reviewed the project team's SingleSidedReinsurancePool, RiskPool, RiskPoolFactory, SalesPolicy, SalesPolicyFactory, Rewarder, and Migration contracts at commit 9c45e6a71ef28161c1dcab8b29408c645af89bed on the team's private Github repository.

Notes on the Contracts:
  • The SingleSidedReinsurancePool contract allows users to stake a single asset determined by the project team into a RiskPool configured by the project team in exchange for rewards.
  • Anyone can use the RiskPoolFactory contract to create new RiskPool instances at any time, but it is intended that a single RiskPool will only be created by the project team.
  • Upon entering the RiskPool, users are minted an amount of shares based on the share price defined in the RiskPool contract. Initially, the price is 1 asset token for 1 share, but this is subject to change as tokens are removed from the Pool via a policy claim.
  • After a policy claim, the share price is recalculated based on the proportion of tokens in the contract to shares in circulation.
  • Only the Claim Assessor address can use the SingleSidedReinsurancePool contract to withdraw any amount of the asset token from the RiskPool contract at any time.
  • Users can transfer their available RiskPool tokens to any address, and the underlying LP is reassigned to the recipient as well.

  • In order for a user to exit their staked position in the RiskPool, users must submit a withdrawal request using the SingleSidedReinsurancePool contract and wait a 10 day lock period in order to withdraw their funds; rewards continue to accrue during the waiting period.
  • Once the wait time has elapsed, users can exchange their shares for an amount of the asset token based on the current share price.
  • Alternatively, users with a pending withdrawal request can use the migrate() function in the SingleSidedReinsurancePool contract to withdraw their staked assets once the wait time has elapsed.
  • Users must exercise caution when using the migrate() function as any remaining shares the user is holding will be burned and their underlying value will be sent to the Migration contract controlled by the project team. In its current state, the tokens sent to the Migration contract are locked forever as there is no way to retrieve them.
  • In the event that there are not enough asset tokens to fulfill the withdrawal request, the contract will only transfer as much as it can provide, and the user's balance record will be eliminated from the system.
  • Users can cancel their withdrawal requests at any time.

  • Rewards are automatically calculated and transferred on deposits and withdraws, but any user may also choose to harvest their rewards manually at any time; please note that the reward distribution depends on the balance of the Rewarder contract, and the transaction will still be successful even if there are not enough tokens in the Rewarder contract to fulfill the distribution.

  • The owner can use the SingleSidedReinsurancePool contract to create new SalesPolicy instances via the SalesPolicyFactory contract at any time.
  • Anyone can use the SalesPolicyFactory contract to create new SalesPolicy instances at any time, but it is intended that SalesPolicies will only be created by the project team.
  • Anyone can use a SalesPolicy contract to purchase coverage offered by the platform.
  • Users are able to specify their own coverage amount, duration, and policy price.
  • The contract uses a signed message to ensure that the signer of the policy is the approved platform signer in order for a user to purchase the policy with the specified terms.
  • The signed message is only valid for a period of 7 days from the time it was signed.
  • Users can only pay for the policy in Uno Re tokens as specified by the SalesPolicy contract.
  • The contract uses the ExchangeAgent to convert the price of the policy from USDT to Uno Re tokens.
  • The SalesPolicy contract mints 1 ERC1155 token to the user for every 1 USDT received from the ExchangeAgent contract.

  • The owner is able to set the ExchangeAgent and PremiumPool contract addresses throughout the platform and in any Policy to any address at any time.
  • The ExchangeAgent and PremiumPool contracts were not provided in the scope of this audit, so we are unable to provide an assessment of these contracts with regards to security.
  • The owner is able to set the token URI for any SalesPolicy contract to any value at any time.
  • The owner is able to set the reward rate for the staking pool to any value at any time.
  • The owner is able to set the Migration and Rewarder contract addresses to any address at any time.
  • The owner is able to set the Claim Assessor address to any address at any time.
  • The owner is able to create a new SalesPolicy and a new RiskPool at any time.
  • When the owner creates a new RiskPool, the previous RiskPool is no longer associated with the platform, and users will lose access to all their staked funds and shares.

  • The team must exercise caution when assigning the staking token to avoid using fee-on-transfer tokens.
  • The contracts utilize ReentrancyGuard to prevent against re-entrancy attacks in applicable functions.
  • The team worked with us to implement changes related to gas optimization.
  • As the contracts are implemented using Solidity v0.8.0, they are safe from any possible overflows/underflows.

Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • Ensure trust in the team as they have substantial control in the ecosystem.
  • Date: November 21th, 2021.
  • Updated: December 27th, 2021 to reflect changes in new commit.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

SingleSidedReinsurancePool Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 +  ReentrancyGuard 
    - [Pub]  #

 + [Lib] Counters 
    - [Int] current
    - [Int] increment #
    - [Int] decrement #
    - [Int] reset #

 + [Int] IMigration 
    - [Ext] onMigration #

 + [Int] IRiskPoolFactory 
    - [Ext] newRiskPool #

 + [Int] ISingleSidedReinsurancePool 
    - [Ext] updatePool #
    - [Ext] enterInPool #
    - [Ext] leaveFromPoolInPending #
    - [Ext] leaveFromPending #
    - [Ext] harvest #
    - [Ext] lpTransfer #
    - [Ext] riskPool
    - [Ext] getProtocolData

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IRewarder 
    - [Ext] onUnoReward #

 + [Int] IRiskPool 
    - [Ext] enter #
    - [Ext] leaveFromPoolInPending #
    - [Ext] leaveFromPending #
    - [Ext] cancelWithrawRequest #
    - [Ext] policyClaim #
    - [Ext] migrateLP #
    - [Ext] setMinLPCapital #
    - [Ext] currency
    - [Ext] getTotalWithdrawRequestAmount
    - [Ext] getWithdrawRequest
    - [Ext] lpPriceUno

 + [Int] ISalesPolicyFactory 
    - [Ext] newSalesPolicy #

 + [Int] ISalesPolicy 
    - [Ext] setPremiumPool #
    - [Ext] setExchangeAgent #
    - [Ext] setSigner #
    - [Ext] setBuyPolicyMaxDeadline #
    - [Ext] setProtocolURI #
    - [Ext] totalUtilizedAmount
    - [Ext] allPoliciesLength
    - [Ext] policyDetail

 + [Lib] TransferHelper 
    - [Int] safeApprove #
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeTransferETH #

 +  SingleSidedReinsurancePool (ISingleSidedReinsurancePool, ReentrancyGuard)
    - [Pub]  #
    - [Ext] allProtocolsLength
    - [Ext] setExchangeAgent #
       - modifiers: onlyOwner
    - [Ext] setExchangeAgentInPolicy #
       - modifiers: onlyOwner
    - [Ext] setSignerInPolicy #
       - modifiers: onlyOwner
    - [Ext] setBuyPolicyMaxDeadlineInPolicy #
       - modifiers: onlyOwner
    - [Ext] setRewardMultiplier #
       - modifiers: onlyOwner
    - [Ext] setRewarder #
       - modifiers: onlyOwner
    - [Ext] setPremiumPool #
       - modifiers: onlyOwner
    - [Ext] setPremiumPoolInPolicy #
       - modifiers: onlyOwner
    - [Ext] setProtocolMCR #
       - modifiers: onlyOwner
    - [Ext] setProtocolURIInPolicy #
       - modifiers: onlyOwner
    - [Ext] setClaimAssessor #
       - modifiers: onlyOwner
    - [Ext] setMigrateTo #
       - modifiers: onlyOwner
    - [Ext] setMinLPCapital #
       - modifiers: onlyOwner
    - [Ext] addProtocol #
       - modifiers: onlyOwner
    - [Ext] createRiskPool #
       - modifiers: onlyOwner,nonReentrant
    - [Ext] migrate #
       - modifiers: nonReentrant
    - [Ext] pendingUno
    - [Pub] updatePool #
    - [Ext] enterInPool #
       - modifiers: nonReentrant
    - [Ext] leaveFromPoolInPending #
       - modifiers: nonReentrant
    - [Ext] leaveFromPending #
       - modifiers: nonReentrant
    - [Ext] lpTransfer #
       - modifiers: nonReentrant
    - [Ext] harvest #
       - modifiers: nonReentrant
    - [Prv] _harvest #
    - [Ext] cancelWithdrawRequest #
       - modifiers: nonReentrant
    - [Ext] policyClaim #
       - modifiers: onlyClaimAssessor,nonReentrant
    - [Ext] getProtocolData
    - [Ext] getStakedAmountPerUser
    - [Ext] getWithdrawRequestPerUser
    - [Ext] getTotalWithdrawPendingAmount

RiskPool and RiskPoolFactory Contracts

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IRiskPoolERC20 
    - [Ext] decimals
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  RiskPoolERC20 (Context, IRiskPoolERC20)
    - [Pub]  #
    - [Ext] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #
    - [Ext] increaseAllowance #
    - [Ext] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #
    - [Int] _withdrawRequest #
    - [Int] _withdrawImplement #
    - [Int] _cancelWithdrawRequest #

 + [Int] ISingleSidedReinsurancePool 
    - [Ext] updatePool #
    - [Ext] enterInPool #
    - [Ext] leaveFromPoolInPending #
    - [Ext] leaveFromPending #
    - [Ext] harvest #
    - [Ext] lpTransfer #
    - [Ext] riskPool
    - [Ext] getProtocolData

 + [Int] IRiskPool 
    - [Ext] enter #
    - [Ext] leaveFromPoolInPending #
    - [Ext] leaveFromPending #
    - [Ext] cancelWithrawRequest #
    - [Ext] policyClaim #
    - [Ext] migrateLP #
    - [Ext] setMinLPCapital #
    - [Ext] currency
    - [Ext] getTotalWithdrawRequestAmount
    - [Ext] getWithdrawRequest
    - [Ext] lpPriceUno

 + [Lib] TransferHelper 
    - [Int] safeApprove #
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeTransferETH #

 +  RiskPool (IRiskPool, RiskPoolERC20)
    - [Pub]  #
    - [Ext] enter #
       - modifiers: onlySSRP
    - [Ext] leaveFromPoolInPending #
       - modifiers: onlySSRP
    - [Ext] leaveFromPending #
       - modifiers: onlySSRP
    - [Ext] cancelWithrawRequest #
       - modifiers: onlySSRP
    - [Ext] policyClaim #
       - modifiers: onlySSRP
    - [Ext] migrateLP #
       - modifiers: onlySSRP
    - [Ext] setMinLPCapital #
       - modifiers: onlySSRP
    - [Ext] getWithdrawRequest
       - modifiers: onlySSRP
    - [Ext] getTotalWithdrawRequestAmount
       - modifiers: onlySSRP
    - [Ext] transfer #
    - [Ext] transferFrom #

 + [Int] IRiskPoolFactory 
    - [Ext] newRiskPool #

 +  RiskPoolFactory (IRiskPoolFactory)
    - [Pub]  #
    - [Ext] newRiskPool #

SalesPolicy and SalesPolicyFactory Contracts

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC165 
    - [Ext] supportsInterface

 + [Int] IERC1155 (IERC165)
    - [Ext] balanceOf
    - [Ext] balanceOfBatch
    - [Ext] setApprovalForAll #
    - [Ext] isApprovedForAll
    - [Ext] safeTransferFrom #
    - [Ext] safeBatchTransferFrom #

 + [Int] IERC1155Receiver (IERC165)
    - [Ext] onERC1155Received #
    - [Ext] onERC1155BatchReceived #

 + [Int] IERC1155MetadataURI (IERC1155)
    - [Ext] uri

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Int] verifyCallResult

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 +  ERC1155 (Context, ERC165, IERC1155, IERC1155MetadataURI)
    - [Pub]  #
    - [Pub] supportsInterface
    - [Pub] uri
    - [Pub] balanceOf
    - [Pub] balanceOfBatch
    - [Pub] setApprovalForAll #
    - [Pub] isApprovedForAll
    - [Pub] safeTransferFrom #
    - [Pub] safeBatchTransferFrom #
    - [Int] _safeTransferFrom #
    - [Int] _safeBatchTransferFrom #
    - [Int] _setURI #
    - [Int] _mint #
    - [Int] _mintBatch #
    - [Int] _burn #
    - [Int] _burnBatch #
    - [Int] _beforeTokenTransfer #
    - [Prv] _doSafeTransferAcceptanceCheck #
    - [Prv] _doSafeBatchTransferAcceptanceCheck #
    - [Prv] _asSingletonArray

 +  ERC1155Receiver (ERC165, IERC1155Receiver)
    - [Pub] supportsInterface

 +  ERC1155Holder (ERC1155Receiver)
    - [Pub] onERC1155Received #
    - [Pub] onERC1155BatchReceived #

 +  ReentrancyGuard 
    - [Pub]  #

 + [Lib] Counters 
    - [Int] current
    - [Int] increment #
    - [Int] decrement #
    - [Int] reset #

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] ISingleSidedReinsurancePool 
    - [Ext] updatePool #
    - [Ext] enterInPool #
    - [Ext] leaveFromPoolInPending #
    - [Ext] leaveFromPending #
    - [Ext] harvest #
    - [Ext] lpTransfer #
    - [Ext] riskPool
    - [Ext] getProtocolData

 + [Int] IExchangeAgent 
    - [Ext] USDT_TOKEN
    - [Ext] getTokenAmountForUSDT
    - [Ext] tokenConvertForUSDTWithTwapPrice #

 + [Int] ISalesPolicy 
    - [Ext] setPremiumPool #
    - [Ext] setExchangeAgent #
    - [Ext] setSigner #
    - [Ext] setBuyPolicyMaxDeadline #
    - [Ext] setProtocolURI #
    - [Ext] totalUtilizedAmount
    - [Ext] allPoliciesLength
    - [Ext] policyDetail

 + [Lib] TransferHelper 
    - [Int] safeApprove #
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeTransferETH #

 +  SalesPolicy (ERC1155, ISalesPolicy, ReentrancyGuard)
    - [Pub]  #
       - modifiers: ERC1155
    - [Ext]  ($)
    - [Ext] buyPolicy ($)
       - modifiers: nonReentrant
    - [Ext] setProtocolURI #
       - modifiers: onlySSRP
    - [Ext] setPremiumPool #
       - modifiers: onlySSRP
    - [Ext] setExchangeAgent #
       - modifiers: onlySSRP
    - [Ext] setSigner #
       - modifiers: onlySSRP
    - [Ext] setBuyPolicyMaxDeadline #
       - modifiers: onlySSRP
    - [Ext] allPoliciesLength
    - [Ext] policyDetail
    - [Prv] getSender

 + [Int] ISalesPolicyFactory 
    - [Ext] newSalesPolicy #

 +  SalesPolicyFactory (ISalesPolicyFactory)
    - [Pub]  #
    - [Ext] newSalesPolicy #

Rewarder Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IRewarder 
    - [Ext] onUnoReward #

 + [Lib] TransferHelper 
    - [Int] safeApprove #
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeTransferETH #

 +  Rewarder (IRewarder)
    - [Pub]  #
    - [Ext] onUnoReward #
       - modifiers: onlySSRP