def test_borrowing_no_collateral(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` with no collateral with reverts('9'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, accounts[9], {'from': accounts[9]}, ) with reverts('9'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, accounts[9], {'from': accounts[9]}, )
def test_rebalance_below_liquidity_threshold(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` borrow_amount = terc20_deposit_amount // 1_000 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # `rebalanceStableBorrowRate()` with less than the liquidity threshold available_liquidity = weth.balanceOf(weth_atoken) total_debt = weth_stable_debt.totalSupply() assert total_debt / (available_liquidity + total_debt) < 0.95 with reverts('22'): lending_pool.rebalanceStableBorrowRate( weth, borrower, {'from': accounts[-1]} )
def test_borrowing_stable_borrow_more_than_max(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Increase price to ensure we have sufficient colalteral price_oracle.setAssetPrice(terc20, price * 1000, {'from': accounts[0]}) # Attempt to `borrow()` more than 25% of the asset's liquidity borrow_amount = deposit_amount * 3 // 10 # > 25% of liquidity with reverts('14'): lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Variable borrowing is still allowed lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_swap_rate_to_stable_with_collateral(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` lending_pool.borrow( weth, 10, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) # Deposit WETH to use as collateral weth.deposit({'from': borrower, 'value': WEI}) weth.approve(lending_pool, WEI, {'from': borrower}) lending_pool.deposit(weth, WEI, borrower, 0, {'from': borrower}) # Attempt to swap with collateral with reverts('13'): lending_pool.swapBorrowRateMode( weth, INTEREST_RATE_MODE_VARIABLE, {'from': borrower} )
def test_borrowing_disable_stable_borrowing_on_reserve(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` while stable borrowing is disabled configurator.disableReserveStableRate(weth, {'from': pool_admin}) borrow_amount = 5 with reverts('12'): lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Variable borrowing is still allowed lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_borrowing_stable_borrow_same_as_collateral(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` the same currency as the collateral (but less than the collateral) borrow_amount = 5 with reverts('13'): lending_pool.borrow( terc20, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Variable borrowing is still allowed lending_pool.borrow( terc20, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_liquidation_call_health_factor(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` variable to set a high overall rate borrow_amount = terc20_deposit_amount / 100 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) with reverts('42'): # Good health factor lending_pool.liquidationCall(weth, terc20, borrower, 1, False, {'from': accounts[7]}) with reverts('42'): # Maximum health factor lending_pool.liquidationCall(weth, terc20, depositer, 1, False, {'from': accounts[7]})
def test_borrowing_insufficient_colalteral(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` with insufficient collateral borrow_amount = terc20_deposit_amount # Note terc20 is priced less than Eth with reverts('11'): lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) with reverts('11'): lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_borrowing_bad_interest_rate_mode(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` with interest made node none or just invalid with reverts('8'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_NONE, 0, borrower, {'from': borrower}, ) with reverts('8'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, 10, 0, borrower, {'from': borrower}, )
def test_borrow_while_frozen(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Attempt to `borrow()` while frozen configurator.freezeReserve(weth, {'from': pool_admin}) with reverts('3'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) with reverts('3'): borrow_amount = 5 lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_liquidation_call_with_no_debt(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, a_erc20, a_erc20_atoken, a_erc20_stable_debt, a_erc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, a_erc20_deposit_amount, price_a) = setup_borrow() # `borrow()` variable to set a high overall rate borrow_amount = a_erc20_deposit_amount / 100 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) # Tank price for aERC20 so we have bad health factor price_a = price_a // 1_000 price_oracle.setAssetPrice(a_erc20, price_a, {'from': accounts[0]}) with reverts('44'): lending_pool.liquidationCall(a_erc20, a_erc20, borrower, 1, False, {'from': accounts[7]})
def test_liquidation_call_not_used_as_collateral(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, a_erc20, a_erc20_atoken, a_erc20_stable_debt, a_erc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, a_erc20_deposit_amount, price_a) = setup_borrow() # `borrow()` variable to set a high overall rate borrow_amount = a_erc20_deposit_amount / 100 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) # Add additional reserve b_erc20 = accounts[0].deploy( MintableDelegationERC20, "b ERC20", "bERC20", 5, ) # Initialise reserve tERC20 (b_erc20_atoken, b_erc20_stable_debt, b_erc20_variable_debt) = setup_new_reserve(configurator, b_erc20, lending_pool, pool_admin) # Turn on collateral and borrowing (b_ecr20_ltv, b_ecr20_threshold, b_ecr20_bonus) = allow_reserve_collateral_and_borrowing(configurator, b_erc20, pool_admin) # Setup price for tERC20 price_b = WEI // 10 # 1 bERC20 : 0.1 ETH price_oracle.setAssetPrice(b_erc20, price_b, {'from': accounts[0]}) # `deposit()` some b_erc20 and turn off use as collateral b_erc20_deposit_amount = deposit_amount b_erc20.mint(b_erc20_deposit_amount, {'from': borrower}) b_erc20.approve(lending_pool, b_erc20_deposit_amount, {'from': borrower}) lending_pool.deposit(b_erc20, b_erc20_deposit_amount, borrower, 0, {'from': borrower}) lending_pool.setUserUseReserveAsCollateral(b_erc20, False, {'from': borrower}) # Tank price for aERC20 so we have bad health factor price_a = price_a // 1_000 price_oracle.setAssetPrice(a_erc20, price_a, {'from': accounts[0]}) with reverts('43'): # Attempt to liquidate collateral that is not being used as collateral lending_pool.liquidationCall(weth, b_erc20, borrower, 1, False, {'from': accounts[7]})
def test_swap_rate_bad_mode(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` lending_pool.borrow( weth, 10, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) lending_pool.borrow( weth, 10, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Attempt to swap with collateral with reverts('8'): lending_pool.swapBorrowRateMode( weth, INTEREST_RATE_MODE_NONE, {'from': borrower} ) # Attempt to swap with collateral with reverts(): lending_pool.swapBorrowRateMode( weth, 3, {'from': borrower} ) # Attempt to swap with collateral with reverts(): lending_pool.swapBorrowRateMode( weth, (1 << 256) - 1, {'from': borrower} )
def test_rebalance_below_rate_threshold(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # Setup price for tERC20 price = WEI * 1000 # 1 tERC20 : 1000 ETH price_oracle.setAssetPrice(terc20, price, {'from': accounts[0]}) available_liquidity = weth.balanceOf(weth_atoken) # `borrow()` variable to set a high overall rate borrow_amount = available_liquidity * 99 // 100 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) # `borrow()` stable getting a very high rate available_liquidity = weth.balanceOf(weth_atoken) tx = lending_pool.borrow( weth, available_liquidity, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # `rebalanceStableBorrowRate()` with less than the rate threshold (but more than liquidity threshold) available_liquidity = weth.balanceOf(weth_atoken) total_debt = weth_stable_debt.totalSupply() assert total_debt / (available_liquidity + total_debt) >= 0.95 # ensure we pass the liquidity threshold check with reverts('22'): lending_pool.rebalanceStableBorrowRate( weth, borrower, {'from': accounts[-1]} )
def test_validate_flash_loan(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, a_erc20, a_erc20_atoken, a_erc20_stable_debt, a_erc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, a_erc20_deposit_amount, price_a) = setup_borrow() with reverts('73'): lending_pool.flashLoan( accounts[0], [weth, weth], [1], [INTEREST_RATE_MODE_NONE], accounts[1], b'', 0, {'from': accounts[1]} )
def test_validate_transfer(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` borrow_amount = terc20_deposit_amount * price // WEI // 10 # 10% of collateral in ETH tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) with reverts('6'): terc20_atoken.transfer(accounts[2], terc20_deposit_amount * 9 // 10, {'from': borrower})
def test_borrowing_bad_health_factor(): (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` so we can manipulate health factor borrow_amount = int(terc20_deposit_amount // 10 * 0.3) lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Decrease tERC20 to 10% of it's value to ruin our health factor price_oracle.setAssetPrice(terc20, price // 10, {'from': accounts[0]}) # We now have bad health factor with reverts('10'): lending_pool.borrow( weth, 1, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) with reverts('10'): lending_pool.borrow( weth, 1, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, )
def test_validate_reserve_as_collateral_deposit_used(): # Deploy and initialize contracts (initializes a weth reserve) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` variable to set a high overall rate borrow_amount = terc20_deposit_amount / 100 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) # `setUserUseReserveAsCollateral()` with reverts('20'): lending_pool.setUserUseReserveAsCollateral(terc20, False, {'from': borrower})
def test_rebalance_attack(): attack_contract = accounts[0].deploy(RebalanceFlashloanAttack) (addresses_provider, lending_pool, configurator, collateral_manager, pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken, weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower, terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus, terc20_deposit_amount, price) = setup_borrow() # `borrow()` stable rate for a user borrow_amount = terc20_deposit_amount // 100 tx = lending_pool.borrow( weth.address, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Deposit WETH and transfer to attack_contract (enough to cover premium of flashloan) weth.deposit({'from': accounts[0], 'value': deposit_amount}) weth.transfer(attack_contract.address, deposit_amount, {'from': accounts[0]}) # Use flashloan to manipulate users rate to max stable rate available_liquidity = weth.balanceOf(weth_atoken.address) tx_b = attack_contract.attackRebalanceFlashloan( lending_pool.address, [weth.address], [available_liquidity], [INTEREST_RATE_MODE_NONE], borrower, b'', ) max_stable_rate = strategy.stableRateSlope1() + strategy.stableRateSlope2() + lending_rate_oracle.getMarketBorrowRate(weth) assert weth_stable_debt.getUserStableRate(borrower) < max_stable_rate