def test_swap_rate_frozen(): # 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) = setup_and_deploy_configuration_with_reserve() # Turn on collateral and borrowing (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Freeze `LendingPool` configurator.freezeReserve(weth, {'from': pool_admin}) with reverts('3'): lending_pool.swapBorrowRateMode( weth, INTEREST_RATE_MODE_STABLE, {'from': accounts[3]} ) with reverts('3'): lending_pool.swapBorrowRateMode( weth, INTEREST_RATE_MODE_VARIABLE, {'from': accounts[3]} )
def test_liquidation_call_deactivated(): (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) = setup_and_deploy_configuration_with_reserve() # Turn on collateral and borrowing (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Add additional reserve terc20 = accounts[0].deploy( MintableDelegationERC20, "Test ERC20", "tERC20", 18, ) # Initialise reserve tERC20 (terc20_atoken, terc20_stable_debt, terc20_variable_debt) = setup_new_reserve(configurator, terc20, lending_pool, pool_admin) # Turn on collateral and borrowing (tecr20_ltv, tecr20_threshold, tecr20_bonus) = allow_reserve_collateral_and_borrowing(configurator, terc20, pool_admin) # Deactivate WETH configurator.deactivateReserve(weth, {'from': pool_admin}) # Note reverts in the delegate call all return '23' with reverts('2'): lending_pool.liquidationCall(weth, terc20, accounts[1], 1, False, {'from': accounts[2]}) with reverts('2'): lending_pool.liquidationCall(terc20, weth, accounts[1], 1, False, {'from': accounts[2]})
def test_repay_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) = setup_and_deploy_configuration_with_reserve() # Turn on collateral and borrowing (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) with reverts('15'): lending_pool.repay( weth, 1, INTEREST_RATE_MODE_STABLE, accounts[3], {'from': accounts[3]} ) with reverts('15'): lending_pool.repay( weth, 1, INTEREST_RATE_MODE_VARIABLE, accounts[3], {'from': accounts[3]} )
def test_withdraw_0x0(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Configure reserve collateral and borrowing (ltv, threhold, bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Create asset and give allowance to lending pool depositor = accounts[4] receiver = accounts[5] deposit_amount = 100 weth.deposit({'from': depositor, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor}) # deposit() referral_code = 500 lending_pool.deposit(weth.address, deposit_amount, depositor, referral_code, {'from': depositor}) # attempt to withdraw to the 0x0 address lending_pool.withdraw(weth.address, deposit_amount, ZERO_ADDRESS, {'from': depositor}) # The zero address now has weth tokens assert weth.balanceOf(ZERO_ADDRESS) == deposit_amount
def test_validate_reserve_as_collateral_no_balance(): # 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) = setup_and_deploy_configuration_with_reserve() # `setUserUseReserveAsCollateral()` with reverts('19'): lending_pool.setUserUseReserveAsCollateral(weth, True, {'from': accounts[4]})
def test_transfers(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Configure reserve collateral and borrowing (ltv, threhold, bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Create asset and give allowance to lending pool depositor = accounts[4] receiver = accounts[5] deposit_amount = 100 weth.deposit({'from': depositor, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor}) # deposit() referral_code = 500 lending_pool.deposit(weth.address, deposit_amount, depositor, referral_code, {'from': depositor}) # Check `AToken` state assert atoken.balanceOf(depositor) == deposit_amount assert atoken.scaledBalanceOf(depositor) == deposit_amount assert atoken.totalSupply() == deposit_amount # Transfer atokens # Should be able to transfer to self tx = atoken.transfer(depositor, deposit_amount, {'from': depositor}) assert tx.events['Transfer']['from'] == depositor assert tx.events['Transfer']['to'] == depositor assert tx.events['Transfer']['value'] == deposit_amount # Should be able to transfer to others tx = atoken.transfer(receiver, deposit_amount, {'from': depositor}) assert tx.events['Transfer']['from'] == depositor assert tx.events['Transfer']['to'] == receiver assert tx.events['Transfer']['value'] == deposit_amount assert atoken.balanceOf(depositor) == 0 assert atoken.balanceOf(receiver) == deposit_amount # Check basic limits with reverts(): # Should not be able to transfer beyond empty balance atoken.transfer(receiver, 1, {'from': depositor}) # Should not be able to transfer to self extra balance atoken.transfer(receiver, deposit_amount + 1, {'from': receiver}) # Should not be able to overflow atoken.transfer(depositor, MAX_UINT256 - 1 , {'from': receiver}) # Should be able to transfer some back atoken.transfer(depositor, deposit_amount/2 , {'from': receiver}) assert atoken.balanceOf(depositor) == deposit_amount/2 assert atoken.balanceOf(receiver) == deposit_amount/2
def test_deposit_invalid_amount(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositer = accounts[4] deposit_amount = 1 weth.deposit({'from': depositer, 'value': deposit_amount}) weth.approve(lending_pool, deposit_amount, {'from': depositer}) # deposit() with reverts('1'): referral_code = 0 lending_pool.deposit(weth, 0, depositer, referral_code, {'from': depositer})
def test_rebalance_deactivated(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositer = accounts[4] deposit_amount = 1 weth.deposit({'from': depositer, 'value': deposit_amount}) weth.approve(lending_pool, deposit_amount, {'from': depositer}) # Deactivate `LendingPool` configurator.deactivateReserve(weth, {'from': pool_admin}) # deposit() with reverts('2'): referral_code = 0 lending_pool.rebalanceStableBorrowRate(weth, depositer, {'from': accounts[-1]})
def test_withdraw_insufficient_balance(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositer_a = accounts[4] amount = 1 weth.deposit({'from': depositer_a, 'value': amount}) weth.approve(lending_pool, amount, {'from': depositer_a}) # `deposit()` referral_code = 0 lending_pool.deposit(weth, amount, depositer_a, referral_code, {'from': depositer_a}) # `withdraw()` more than balance with reverts('5'): lending_pool.withdraw(weth, amount + 1, depositer_a, {'from': depositer_a})
def test_withdraw_deactivated(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositer_a = accounts[4] amount = 1 weth.deposit({'from': depositer_a, 'value': amount}) weth.approve(lending_pool, amount, {'from': depositer_a}) # `deposit()` referral_code = 0 lending_pool.deposit(weth, amount, depositer_a, referral_code, {'from': depositer_a}) # Note this actually reverts due to deactivateReserve() having liquidity with reverts(): # Deactivate `LendingPool` configurator.deactivateReserve(weth, {'from': pool_admin}) # `withdraw()` while deactivated lending_pool.withdraw(weth, 1, depositer_a, {'from': depositer_a})
def test_validation(): # 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, atoken, stable_debt, variable_debt, strategy) = setup_and_deploy_configuration_with_reserve() # Configure reserve collateral and borrowing (ltv, threhold, bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Create asset and give allowance to lending pool depositor = accounts[4] receiver = accounts[5] deposit_amount = 100 weth.deposit({'from': depositor, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor}) # deposit() referral_code = 500 tx = lending_pool.deposit(weth.address, deposit_amount, depositor, referral_code, {'from': depositor}) with reverts('29'): # Should not be able to transfer beyond empty balance atoken.mint(depositor, 100, 0, {'from': depositor}) atoken.burn(depositor, depositor, 100, 0, {'from': depositor})
def test_repay_max_on_behalf_of(): # 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) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositer = accounts[4] deposit_amount = 10_000_000_000_000_000_000 weth.deposit({'from': depositer, 'value': deposit_amount}) weth.approve(lending_pool, deposit_amount, {'from': depositer}) # Turn on collateral and borrowing (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Set market lending rate lending_rate_oracle.setMarketBorrowRate(weth, MARKET_BORROW_RATE) # `deposit()` weth lending_pool.deposit(weth, deposit_amount, depositer, 0, {'from': depositer}) # Add additional reserve terc20 = accounts[0].deploy( MintableDelegationERC20, "Test ERC20", "tERC20", 18, ) # Initialise reserve tERC20 (terc20_atoken, terc20_stable_debt, terc20_variable_debt) = setup_new_reserve(configurator, terc20, lending_pool, pool_admin) # Turn on collateral and borrowing (tecr20_ltv, tecr20_threshold, tecr20_bonus) = allow_reserve_collateral_and_borrowing(configurator, terc20, pool_admin) # Setup price for tERC20 price = WEI // 10 # 1 tERC20 : 0.1 ETH price_oracle.setAssetPrice(terc20, price, {'from': accounts[0]}) # Create tERC20 tokens for `borrower` and deposit them into `LendingPool` borrower = accounts[5] terc20_deposit_amount = deposit_amount // 10 terc20.mint(terc20_deposit_amount, {'from': borrower}) terc20.approve(lending_pool, terc20_deposit_amount, {'from': borrower}) lending_pool.deposit(terc20, terc20_deposit_amount, borrower, 0, {'from': borrower}) # `borrow()` borrow_amount = terc20_deposit_amount // 1000 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) with reverts('16'): lending_pool.repay( weth, (1 << 256) - 1, INTEREST_RATE_MODE_STABLE, borrower, {'from': accounts[-1]} ) # `borrow()` borrow_amount = terc20_deposit_amount // 1000 tx = lending_pool.borrow( weth, borrow_amount, INTEREST_RATE_MODE_VARIABLE, 0, borrower, {'from': borrower}, ) with reverts('16'): lending_pool.repay( weth, (1 << 256) - 1, INTEREST_RATE_MODE_VARIABLE, borrower, {'from': accounts[-1]} )
def test_deposit_withdraw(): # 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) = setup_and_deploy_configuration_with_reserve() # Create asset and give allowance to lending pool depositor = accounts[4] depositor2 = accounts[11] depositor3 = accounts[12] deposit_amount = 1_000_000_000_000 weth.deposit({'from': depositor, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor}) weth.deposit({'from': depositor2, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor2}) weth.deposit({'from': depositor3, 'value': deposit_amount}) weth.approve(lending_pool.address, deposit_amount, {'from': depositor3}) # Turn on collateral and borrowing (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin) # Set market lending rate lending_rate_oracle.setMarketBorrowRate(weth.address, MARKET_BORROW_RATE) # `deposit()` weth lending_pool.deposit(weth.address, deposit_amount, depositor, 0, {'from': depositor}) # Check the atoken balance of the first depositor assert weth_atoken.balanceOf(depositor) == deposit_amount # Add additional reserve terc20 = accounts[0].deploy( MintableDelegationERC20, "Test ERC20", "tERC20", 18, ) # Initialise reserve tERC20 (terc20_atoken, terc20_stable_debt, terc20_variable_debt) = setup_new_reserve(configurator, terc20, lending_pool, pool_admin) # Turn on collateral and borrowing (tecr20_ltv, tecr20_threshold, tecr20_bonus) = allow_reserve_collateral_and_borrowing(configurator, terc20, pool_admin) # Setup price for tERC20 price = WEI // 10 # 1 tERC20 : 0.1 ETH price_oracle.setAssetPrice(terc20.address, price, {'from': accounts[0]}) ### First Borrower ### # Create tERC20 tokens for `borrower` and deposit them into `LendingPool` borrower = accounts[5] terc20_deposit_amount = (deposit_amount * 5 + 1) // 0.3 # The collateral will allow us to borrow up half the amount of the original deposit. (30% ltv) terc20.mint(terc20_deposit_amount, {'from': borrower}) terc20.approve(lending_pool.address, terc20_deposit_amount, {'from': borrower}) lending_pool.deposit(terc20.address, terc20_deposit_amount, borrower, 0, {'from': borrower}) # `borrow()` # Should not be able to borrow more than the original deposit with reverts('11'): tx1 = lending_pool.borrow( weth.address, deposit_amount // 2 + 1, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # Should be able to borrow the deposit amount however borrow_amount = deposit_amount // 2 tx1 = lending_pool.borrow( weth.address, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, borrower, {'from': borrower}, ) # The token balance should have increased # Calculate the normalized reserve income of weth reserve_data = lending_pool.getReserveData(weth.address) time_diff = 0 cumulated = ray_mul(calculate_linear_interest(reserve_data[3], time_diff), reserve_data[1]) assert cumulated == lending_pool.getReserveNormalizedIncome(weth.address) # Wait for some interest to accrue web3.manager.request_blocking("evm_increaseTime", 4) ### Second Borrower ### # Create tERC20 tokens for `second_borrower_funder` and deposit them into `LendingPool` second_borrower_funder = accounts[10] ## The account that will actually borrow second_borrower = accounts[6] ## The account that will perform the borrow on behalf of the second borrower borrow_behalf = accounts[7] terc20.mint(terc20_deposit_amount, {'from': second_borrower_funder}) terc20.approve(lending_pool.address, terc20_deposit_amount, {'from': second_borrower_funder}) ## Borrow on behalf of a random user tx2 = lending_pool.deposit(terc20.address, terc20_deposit_amount, second_borrower, 10, {'from': second_borrower_funder}) # Calculate the normalized reserve income of weth reserve_data = lending_pool.getReserveData(weth.address) time_diff = tx2.timestamp - tx1.timestamp cumulated = ray_mul(calculate_linear_interest(reserve_data[3], time_diff), reserve_data[1]) assert cumulated == lending_pool.getReserveNormalizedIncome(weth.address) assert weth_atoken.balanceOf(depositor) == ray_mul(cumulated, deposit_amount) ## Allow borrow_behalf to borrow on behalf of second_borrower weth_stable_debt.approveDelegation(borrow_behalf, borrow_amount, {'from': second_borrower}) tx3 = lending_pool.borrow( weth.address, borrow_amount, INTEREST_RATE_MODE_STABLE, 0, second_borrower, {'from': borrow_behalf}, ) ## Check the balances reserve_data = lending_pool.getReserveData(weth.address) time_diff = 0 cumulated = ray_mul(calculate_linear_interest(reserve_data[3], time_diff), reserve_data[1]) assert cumulated == lending_pool.getReserveNormalizedIncome(weth.address) assert weth_atoken.balanceOf(depositor) == ray_mul(cumulated, deposit_amount) # We have borrowed all the weth assert weth.balanceOf(weth_atoken.address) == 0 assert terc20_atoken.balanceOf(second_borrower_funder) == 0 assert terc20_atoken.balanceOf(second_borrower) == terc20_deposit_amount assert weth.balanceOf(borrow_behalf) == borrow_amount assert weth_stable_debt.balanceOf(second_borrower) == borrow_amount assert weth.balanceOf(second_borrower) == 0 # A second depositor comes along and deposits weth tx4 = lending_pool.deposit(weth.address, deposit_amount, depositor2, 45, {'from': depositor2}) ## Check the balance of depositor2 reserve_data = lending_pool.getReserveData(weth.address) assert weth_atoken.scaledBalanceOf(depositor2) == ray_div(deposit_amount, reserve_data[1]) # Wait for some interest to accrue web3.manager.request_blocking("evm_increaseTime", 4) tx5 = lending_pool.deposit(weth.address, deposit_amount, depositor3, 0, {'from': depositor3}) # Depositors interest should be 1 > 2 > 3. reserve_data = lending_pool.getReserveData(weth.address) time_diff = 0 cumulated = ray_mul(calculate_linear_interest(reserve_data[3], time_diff), reserve_data[1]) assert cumulated == lending_pool.getReserveNormalizedIncome(weth.address) # Check the balances assert weth_atoken.scaledBalanceOf(depositor) == deposit_amount ## The last deposit should be scaled assert weth_atoken.scaledBalanceOf(depositor3) == ray_div(deposit_amount, reserve_data[1]) assert weth_atoken.balanceOf(depositor) == ray_mul(cumulated, weth_atoken.scaledBalanceOf(depositor)) assert weth_atoken.balanceOf(depositor2) == ray_mul(cumulated, weth_atoken.scaledBalanceOf(depositor2)) assert weth_atoken.balanceOf(depositor3) == ray_mul(cumulated, weth_atoken.scaledBalanceOf(depositor3)) assert weth_atoken.balanceOf(depositor) > weth_atoken.balanceOf(depositor2) assert weth_atoken.balanceOf(depositor2) > weth_atoken.balanceOf(depositor3) ## Verify basic withdrawal logic # At this point: # Depositor, Depositor2 and Depositor3 have deposited `deposit_amount` of # weth. # There have been 2 borrows each requesting half of the deposit_amount. # There should remain 2 `deposit_amount` weth left and should be withdrawable assert weth.balanceOf(weth_atoken.address) == 2* deposit_amount # Initial depositor can withdraw excess due to interest. lending_pool.withdraw(weth.address, deposit_amount + 1, ZERO_ADDRESS, {'from': depositor} ) with reverts('5'): # The depositor cannot withdraw all the remaining funds lending_pool.withdraw(weth.address, deposit_amount - 1, ZERO_ADDRESS, {'from': depositor} ) with reverts(): # The second depositor cannot withdraw more than was deposited lending_pool.withdraw(weth.address, deposit_amount, ZERO_ADDRESS, {'from': depositor2} ) # The second depositor can withdraw the remaining underlying weth lending_pool.withdraw(weth.address, deposit_amount - 1, ZERO_ADDRESS, {'from': depositor2} ) with reverts(): # The third depositor cannot withdraw anything lending_pool.withdraw(weth.address, 1, ZERO_ADDRESS, {'from': depositor2} )