BACKED - Smart Contract Audit Report
Summary
BACKED is building an insurance protocol, where users can provide or receive insurance for approved ERC-20 tokens.
For this audit, we reviewed the project team's BACKED and UniswapPriceProvider contracts with code that was provided to us.
Notes on the Contracts:Audit Findings Summary:
- The BACKED contract allows anyone to offer to give insurance or to receive insurance, as long as the asset pair is supported by the system.
- The insurer provides a “loss coverage” amount, which is transferred to the contract balance in the policy’s defined base currency; this is intended for covering losses of the insured.
- The insured pays a platform deposit fee in AGIO token and a percentage of the insured asset amount as premium to the contract address; this percentage is defined in the policy terms.
- The platform deposit fee is calculated by taking a percentage of the total premium for the period and converting it to AGIO; the percentage is defined by the project team on deployment and cannot be altered.
- If an offer that has not been accepted yet is canceled, the platform deposit fee and premium payment is transferred back to the creator of the offer.
- On policy acceptance, 10% of the platform deposit fee is burned.
- Anyone may initiate a premium withdrawal for a specific policy; the available premium amount will be transferred to the insurer.
- Users are able to deposit premium for future periods, but the contract address must be approved for the amount due, or the transaction will fail.
- Users will not be able to deposit the premium if the payment for the period is overdue; this will lead to policy termination.
- On termination, there will be a final payout to both parties; either party may terminate an accepted policy at any time.
- The insured party will not be eligible for loss coverage returns if the premium is unpaid; otherwise, the insured party may receive up to a maximum value of the amount specified in the policy for loss coverage, depending on the difference between the original price and the price at termination of the asset.
- The remaining part of the loss coverage amount will go back to the insurer.
- Both parties will receive the amount due to them, rounded up or down on the week depending on the terminating party’s role in the policy.
- The insured party will not be eligible for premium returns if the premium is unpaid.
- The contract address must be approved for at least the amount owed, or the entire transaction will revert.
- The project team may transfer deposit fees in AGIO from the contract address to any wallet address specified at any time only for policies that have been accepted.
- The project team may change the burn percentage at any time.
- The platform uses UniswapV3 Oracle to determine prices.
- The team has worked with us to improve these contracts for gas optimization.
- No security issues from outside attackers were identified.
- The platform should not be used with ERC-777 tokens to prevent re-entrancy issues. This is uncommon.
- The project team should not add their own AGIO token as an approved asset, as premiums can be subject to token theft due to the owner's ability to transfer AGIO out of the contract at any time.
- Ensure trust in the team as they have some control in the ecosystem.
- Date: July 5th, 2021.
Audit Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | Pass |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
BACKED Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Int] IPriceProvider
- [Ext] getPairPrice
+ [Int] IBurnable
- [Ext] burn #
+ [Int] IERC20Extented (IERC20)
- [Ext] decimals
+ Backed (Ownable)
- [Pub] #
- [Pub] addPair #
- modifiers: onlyOwner
- [Pub] placeOfferByInsurer #
- [Pub] acceptOfferByInsurer #
- [Pub] placeOfferByInsured #
- [Pub] acceptOfferByInsured #
- [Pub] premiumDeposit #
- [Pub] cancelOfferByInsured #
- [Pub] premiumWithdraval #
- [Pub] transferFee #
- modifiers: onlyOwner
- [Pub] terminate #
- [Pub] platformFee
- [Prv] _plaformFeeAsset
- [Pub] getCurrentPolicyId
- [Pub] assetPrice
- [Pub] weekElapsed
- [Pub] weelElapsedRoundUp
- [Pub] premiumAvailableInsurerWithdrawal
- [Pub] premiumPerWeek
- [Pub] weelElapsedRoundDown
- [Pub] enoughPremium
- [Pub] expire
- [Pub] getPolicy
- [Prv] _insurerOfferLogic #
- [Prv] _acceptFee #
- [Prv] _insuredOfferLogic #
- [Prv] _premiumDepositLogic #
- [Int] _getPolicyId #
UniswapPriceProvider Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] FullMath
- [Int] mulDiv
- [Int] mulDivRoundingUp
+ [Lib] TickMath
- [Int] getSqrtRatioAtTick
- [Int] getTickAtSqrtRatio
+ [Int] IUniswapV3PoolImmutables
- [Ext] factory
- [Ext] token0
- [Ext] token1
- [Ext] fee
- [Ext] tickSpacing
- [Ext] maxLiquidityPerTick
+ [Int] IUniswapV3PoolState
- [Ext] slot0
- [Ext] feeGrowthGlobal0X128
- [Ext] feeGrowthGlobal1X128
- [Ext] protocolFees
- [Ext] liquidity
- [Ext] ticks
- [Ext] tickBitmap
- [Ext] positions
- [Ext] observations
+ [Int] IUniswapV3PoolDerivedState
- [Ext] observe
- [Ext] snapshotCumulativesInside
+ [Int] IUniswapV3PoolActions
- [Ext] initialize #
- [Ext] mint #
- [Ext] collect #
- [Ext] burn #
- [Ext] swap #
- [Ext] flash #
- [Ext] increaseObservationCardinalityNext #
+ [Int] IUniswapV3PoolOwnerActions
- [Ext] setFeeProtocol #
- [Ext] collectProtocol #
+ [Int] IUniswapV3PoolEvents
+ [Int] IUniswapV3Pool (IUniswapV3PoolImmutables, IUniswapV3PoolState, IUniswapV3PoolDerivedState, IUniswapV3PoolActions, IUniswapV3PoolOwnerActions, IUniswapV3PoolEvents)
+ [Lib] LowGasSafeMath
- [Int] add
- [Int] sub
- [Int] mul
- [Int] add
- [Int] sub
+ [Lib] PoolAddress
- [Int] getPoolKey
- [Int] computeAddress
+ [Lib] OracleLibrary
- [Int] consult
- [Int] getQuoteAtTick
+ [Int] IPriceProvider
- [Ext] getPairPrice
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC20Extented (IERC20)
- [Ext] decimals
+ UniswapPriceProvider (Ownable)
- [Ext] getPairPrice