diff --git a/contracts/Strategy.sol b/contracts/Strategy.sol index fe23b7c..8ca26db 100644 --- a/contracts/Strategy.sol +++ b/contracts/Strategy.sol @@ -23,7 +23,7 @@ import "./Interfaces/Compound/ComptrollerI.sol"; interface IUni{ function getAmountsOut( - uint256 amountIn, + uint256 amountIn, address[] calldata path ) external view returns (uint256[] memory amounts); @@ -173,7 +173,7 @@ contract Strategy is BaseStrategy { * NOTE: this call and `tendTrigger` should never return `true` at the same time. */ function harvestTrigger(uint256 gasCost) public override view returns (bool) { - + StrategyParams memory params = vault.strategies(address(this)); // Should not trigger if strategy is not activated @@ -224,11 +224,11 @@ contract Strategy is BaseStrategy { path[1] = end; }else{ path = new address[](3); - path[0] = start; - path[1] = weth; + path[0] = start; + path[1] = weth; path[2] = end; } - + uint256[] memory amounts = IUni(uniswapRouter).getAmountsOut(_amount, path); return amounts[amounts.length - 1]; @@ -288,12 +288,12 @@ contract Strategy is BaseStrategy { if(totalSupply > 0){ blockShareSupply = deposits.mul(distributionPerBlock).div(totalSupply); } - + uint256 blockShareBorrow = 0; if(totalBorrow > 0){ blockShareBorrow = borrows.mul(distributionPerBlock).div(totalBorrow); } - + //how much we expect to earn per block uint256 blockShare = blockShareSupply.add(blockShareBorrow); @@ -354,7 +354,7 @@ contract Strategy is BaseStrategy { //no position to harvest //but we may have some debt to return //it is too expensive to free more debt in this method so we do it in adjust position - _debtPayment = Math.min(wantBalance, _debtOutstanding); + _debtPayment = Math.min(wantBalance, _debtOutstanding); return (_profit, _loss, _debtPayment); } (uint256 deposits, uint256 borrows) = getLivePosition(); @@ -376,7 +376,7 @@ contract Strategy is BaseStrategy { _profit = balance - debt; if (wantBalance < _profit) { - //all reserve is profit + //all reserve is profit _profit = wantBalance; } else if (wantBalance > _profit.add(_debtOutstanding)){ _debtPayment = _debtOutstanding; @@ -408,15 +408,15 @@ contract Strategy is BaseStrategy { if(_wantBal < _debtOutstanding){ //this is graceful withdrawal. dont use backup //we use more than 1 because withdrawunderlying causes problems with 1 token due to different decimals - if(cToken.balanceOf(address(this)) > 1){ + if(cToken.balanceOf(address(this)) > 1){ _withdrawSome(_debtOutstanding - _wantBal, false); } return; } - + (uint256 position, bool deficit) = _calculateDesiredPosition(_wantBal - _debtOutstanding, true); - + //if we are below minimun want change it is not worth doing //need to be careful in case this pushes to liquidation if (position > minWant) { @@ -473,7 +473,9 @@ contract Strategy is BaseStrategy { if(collateralTarget > 0){ AmountNeeded = borrowBalance.mul(1e18).div(collateralTarget); } - uint256 redeemable = depositBalance.sub(AmountNeeded); + + uint256 redeemable = depositBalance > AmountNeeded ? depositBalance.sub(AmountNeeded) : depositBalance; + //uint256 redeemable = depositBalance.sub(AmountNeeded); if (redeemable < _amount) { cToken.redeemUnderlying(redeemable); @@ -509,7 +511,7 @@ contract Strategy is BaseStrategy { uint256 desiredSupply = 0; if (dep) { desiredSupply = unwoundDeposit.add(balance); - } else { + } else { if(balance > unwoundDeposit) balance = unwoundDeposit; desiredSupply = unwoundDeposit.sub(balance); } @@ -557,12 +559,12 @@ contract Strategy is BaseStrategy { (uint256 deposits, uint256 borrows) = getLivePosition(); //1 token causes rounding error with withdrawUnderlying - if(cToken.balanceOf(address(this)) > 1){ + if(cToken.balanceOf(address(this)) > 1){ _withdrawSome(deposits.sub(borrows), true); } _amountFreed = Math.min(_amountNeeded, want.balanceOf(address(this))); - + } else { if (_balance < _amountNeeded) { _withdrawSome(_amountNeeded.sub(_balance), true); @@ -666,6 +668,7 @@ contract Strategy is BaseStrategy { } //maxDeleverage is how much we want to increase by + event Debug(uint256 theoreticalBorrow, uint256 borrowed); function _normalLeverage( uint256 maxLeverage, uint256 lent, @@ -674,6 +677,11 @@ contract Strategy is BaseStrategy { ) internal returns (uint256 leveragedAmount) { uint256 theoreticalBorrow = lent.mul(collatRatio).div(1e18); + emit Debug(theoreticalBorrow, borrowed); + if (borrowed > theoreticalBorrow) { + return 0; + } + leveragedAmount = theoreticalBorrow.sub(borrowed); if (leveragedAmount >= maxLeverage) { diff --git a/tests/MattCustom/conftest.py b/tests/MattCustom/conftest.py index be91959..e20694d 100644 --- a/tests/MattCustom/conftest.py +++ b/tests/MattCustom/conftest.py @@ -52,8 +52,7 @@ def uni_liquidity(accounts): @pytest.fixture def unitoken(): - token_address = "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984" - yield Contract(token_address) + yield Contract("0x1f9840a85d5af5bf1d1762f925bdaddc4201f984") @pytest.fixture def cUni(): @@ -99,21 +98,22 @@ def newstrategy( newstrategy.setKeeper(keeper) yield newstrategy + @pytest.fixture def uniLend(): - address = "0x5e882c9f00209315e049B885B9b3dfbEe60D80A4" - yield Contract.from_explorer(address) + yield Contract("0x5e882c9f00209315e049B885B9b3dfbEe60D80A4") + @pytest.fixture def me(accounts): yield accounts.at("0x1a123d835B006d27d4978C8EB40B14f08e0b8607", force=True) + @pytest.fixture def liveGov(accounts): yield accounts.at("0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52", force=True) + @pytest.fixture def liveVault(): - address = "0xFBEB78a723b8087fD2ea7Ef1afEc93d35E8Bed42" - yield Contract.from_explorer(address) - + yield Contract("0xFBEB78a723b8087fD2ea7Ef1afEc93d35E8Bed42") diff --git a/tests/MattCustom/test_operation_uni.py b/tests/MattCustom/test_operation_uni.py index 79f44b7..9c03e48 100644 --- a/tests/MattCustom/test_operation_uni.py +++ b/tests/MattCustom/test_operation_uni.py @@ -1,13 +1,5 @@ -# TODO: Add tests here that show the normal operation of this strategy -# Suggestions to include: -# - strategy loading and unloading (via Vault addStrategy/revokeStrategy) -# - change in loading (from low to high and high to low) -# - strategy operation at different loading levels (anticipated and "extreme") - import pytest - -from brownie import Wei, accounts, Contract, config -from brownie import Strategy +from brownie import Wei, accounts, Contract, config, Strategy, ZERO_ADDRESS @pytest.mark.require_network("mainnet-fork") @@ -47,8 +39,15 @@ def test_operation( liveVault.setManagementFee(0, {"from": liveGov}) liveVault.setPerformanceFee(0, {"from": liveGov}) - liveVault.updateStrategyDebtRatio(uniLend, 3800, {"from": liveGov}) - liveVault.addStrategy(strategy, 3_000, 0, 2 ** 256 - 1, 1_000, {"from": liveGov}) + + for i in range(0, 20): + strat = liveVault.withdrawalQueue(i) + if strat == ZERO_ADDRESS: + break + + liveVault.revokeStrategy(strat, {"from": liveGov}) + + liveVault.addStrategy(strategy, 10_000, 0, 2 ** 256 - 1, 1_000, {"from": liveGov}) # First harvest uniLend.harvest({"from": liveGov})