From 1a5c894bb940f7da27de3acfebea933cd340ad8f Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 2 Jan 2024 15:26:36 -0700 Subject: [PATCH 1/7] test: for no locking --- contracts/VaultV3.vy | 10 +++++++--- tests/unit/vault/test_profit_unlocking.py | 8 +++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 7b727fec..01b42a2a 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -1329,14 +1329,18 @@ def _process_report(strategy: address) -> (uint256, uint256): # Record the report of profit timestamp. self.strategies[strategy].last_report = block.timestamp - # We have to recalculate the fees paid for cases with an overall loss. + # We have to recalculate the fees paid for cases with an overall loss or now profit locking + if loss + total_fees > gain + total_refunds or profit_max_unlock_time == 0: + protocol_fees = self._convert_to_assets(protocol_fees_shares, Rounding.ROUND_DOWN) + total_fees = self._convert_to_assets(protocol_fees_shares + accountant_fees_shares, Rounding.ROUND_DOWN) + log StrategyReported( strategy, gain, loss, self.strategies[strategy].current_debt, - self._convert_to_assets(protocol_fees_shares, Rounding.ROUND_DOWN), - self._convert_to_assets(protocol_fees_shares + accountant_fees_shares, Rounding.ROUND_DOWN), + protocol_fees, + total_fees, total_refunds ) diff --git a/tests/unit/vault/test_profit_unlocking.py b/tests/unit/vault/test_profit_unlocking.py index 18a05cfc..6d382a07 100644 --- a/tests/unit/vault/test_profit_unlocking.py +++ b/tests/unit/vault/test_profit_unlocking.py @@ -3002,9 +3002,15 @@ def test_set_profit_max_period_to_zero__with_fees_doesnt_lock( expected_fees_shares = first_profit * performance_fee / MAX_BPS_ACCOUNTANT first_price_per_share = vault.pricePerShare() + expected_fee_amount = ( + expected_fees_shares + * (amount + first_profit) + // (amount + expected_fees_shares) + ) + # Fees will immediately unlock as well when not locking. create_and_check_profit( - asset, strategy, gov, vault, first_profit, by_pass_fees=True + asset, strategy, gov, vault, first_profit, total_fees=expected_fee_amount ) # All profits should have been unlocked From df72ccb51a9d6fe540c580570ae5b6878a380a9e Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 2 Jan 2024 16:16:45 -0700 Subject: [PATCH 2/7] chore: cheaper reports --- contracts/VaultV3.vy | 45 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 01b42a2a..c3cbefe2 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -1211,29 +1211,20 @@ def _process_report(strategy: address) -> (uint256, uint256): # For Accountant fee assessment. total_fees: uint256 = 0 total_refunds: uint256 = 0 - # For Protocol fee assessment. - protocol_fees: uint256 = 0 - protocol_fee_recipient: address = empty(address) accountant: address = self.accountant # If accountant is not set, fees and refunds remain unchanged. if accountant != empty(address): total_fees, total_refunds = IAccountant(accountant).report(strategy, gain, loss) - # Protocol fees will be 0 if accountant fees are 0. - if total_fees > 0: - protocol_fee_bps: uint16 = 0 - # Get the config for this vault. - protocol_fee_bps, protocol_fee_recipient = IFactory(self.factory).protocol_fee_config() - - if(protocol_fee_bps > 0): - # Protocol fees are a percent of the fees the accountant is charging. - protocol_fees = total_fees * convert(protocol_fee_bps, uint256) / MAX_BPS + # For Protocol fee assessment. + protocol_fee_bps: uint16 = 0 + protocol_fee_recipient: address = empty(address) # `shares_to_burn` is derived from amounts that would reduce the vaults PPS. # NOTE: this needs to be done before any pps changes shares_to_burn: uint256 = 0 - accountant_fees_shares: uint256 = 0 + total_fees_shares: uint256 = 0 protocol_fees_shares: uint256 = 0 # Only need to burn shares if there is a loss or fees. if loss + total_fees > 0: @@ -1242,10 +1233,16 @@ def _process_report(strategy: address) -> (uint256, uint256): # Vault calculates the amount of shares to mint as fees before changing totalAssets / totalSupply. if total_fees > 0: - # Accountant fees are total fees - protocol fees. - accountant_fees_shares = self._convert_to_shares(total_fees - protocol_fees, Rounding.ROUND_DOWN) - if protocol_fees > 0: - protocol_fees_shares = self._convert_to_shares(protocol_fees, Rounding.ROUND_DOWN) + # Get the total amount shares to issue for the fees. + total_fees_shares = self._convert_to_shares(total_fees, Rounding.ROUND_DOWN) + + # Get the config for this vault. + protocol_fee_bps, protocol_fee_recipient = IFactory(FACTORY).protocol_fee_config() + + # If there is a protocol fee. + if protocol_fee_bps > 0: + # Get the percent of fees to go to protocol fees. + protocol_fees_shares = total_fees_shares * convert(protocol_fee_bps, uint256) / MAX_BPS # Shares to lock is any amounts that would otherwise increase the vaults PPS. newly_locked_shares: uint256 = 0 @@ -1295,8 +1292,9 @@ def _process_report(strategy: address) -> (uint256, uint256): previously_locked_shares -= (shares_to_burn - shares_not_to_lock) # Issue shares for fees that were calculated above if applicable. - if accountant_fees_shares > 0: - self._issue_shares(accountant_fees_shares, accountant) + if total_fees_shares > 0: + # Accountant fees are (total_fees - protocol_fees). + self._issue_shares(total_fees_shares - protocol_fees_shares, accountant) if protocol_fees_shares > 0: self._issue_shares(protocol_fees_shares, protocol_fee_recipient) @@ -1329,17 +1327,16 @@ def _process_report(strategy: address) -> (uint256, uint256): # Record the report of profit timestamp. self.strategies[strategy].last_report = block.timestamp - # We have to recalculate the fees paid for cases with an overall loss or now profit locking + # We have to recalculate the fees paid for cases with an overall loss or no profit locking if loss + total_fees > gain + total_refunds or profit_max_unlock_time == 0: - protocol_fees = self._convert_to_assets(protocol_fees_shares, Rounding.ROUND_DOWN) - total_fees = self._convert_to_assets(protocol_fees_shares + accountant_fees_shares, Rounding.ROUND_DOWN) + total_fees = self._convert_to_assets(total_fees_shares, Rounding.ROUND_DOWN) log StrategyReported( strategy, gain, loss, - self.strategies[strategy].current_debt, - protocol_fees, + unsafe_sub(unsafe_add(current_debt, gain), loss), + total_fees * convert(protocol_fee_bps, uint256) / MAX_BPS, total_fees, total_refunds ) From 50cf1dadb8c9f04a04c9a6369bf10dedf6a25236 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 2 Jan 2024 17:41:00 -0700 Subject: [PATCH 3/7] chore: track current debt --- contracts/VaultV3.vy | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index c3cbefe2..18636b68 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -1259,7 +1259,8 @@ def _process_report(strategy: address) -> (uint256, uint256): # Record any reported gains. if gain > 0: # NOTE: this will increase total_assets - self.strategies[strategy].current_debt += gain + current_debt = unsafe_add(current_debt, gain) + self.strategies[strategy].current_debt = current_debt self.total_debt += gain profit_max_unlock_time: uint256 = self.profit_max_unlock_time @@ -1269,7 +1270,8 @@ def _process_report(strategy: address) -> (uint256, uint256): # Strategy is reporting a loss if loss > 0: - self.strategies[strategy].current_debt -= loss + current_debt = unsafe_sub(current_debt, loss) + self.strategies[strategy].current_debt = current_debt self.total_debt -= loss # NOTE: should be precise (no new unlocked shares due to above's burn of shares) @@ -1335,7 +1337,7 @@ def _process_report(strategy: address) -> (uint256, uint256): strategy, gain, loss, - unsafe_sub(unsafe_add(current_debt, gain), loss), + current_debt, total_fees * convert(protocol_fee_bps, uint256) / MAX_BPS, total_fees, total_refunds From 747bdfa3fd4ec1629a66b14db7a8242deca1a631 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Fri, 12 Jan 2024 10:18:42 -0700 Subject: [PATCH 4/7] chore: lower unlocked gas --- contracts/VaultV3.vy | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 18636b68..61917a17 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -221,8 +221,7 @@ balance_of: HashMap[address, uint256] # ERC20 - owner -> (spender -> amount) allowance: public(HashMap[address, HashMap[address, uint256]]) # Total amount of shares that are currently minted including those locked. -# NOTE: To get the ERC20 compliant version user totalSupply(). -total_supply: public(uint256) +total_supply: uint256 # Total amount of assets that has been deposited in strategies. total_debt: uint256 # Current assets held in the vault contract. Replacing balanceOf(this) to avoid price_per_share manipulation. @@ -428,14 +427,13 @@ def _burn_unlocked_shares(): # Get the amount of shares that have unlocked unlocked_shares: uint256 = self._unlocked_shares() + # Update last profit time no matter what. + self.last_profit_update = block.timestamp + # IF 0 there's nothing to do. if unlocked_shares == 0: return - # Only do an SSTORE if necessary - if self.full_profit_unlock_date > block.timestamp: - self.last_profit_update = block.timestamp - # Burn the shares unlocked. self._burn_shares(unlocked_shares, self) @@ -1318,13 +1316,11 @@ def _process_report(strategy: address) -> (uint256, uint256): self.profit_unlocking_rate = total_locked_shares * MAX_BPS_EXTENDED / new_profit_locking_period # Calculate how long until the full amount of shares is unlocked. self.full_profit_unlock_date = block.timestamp + new_profit_locking_period - # Update the last profitable report timestamp. - self.last_profit_update = block.timestamp else: - # NOTE: only setting this to 0 will turn in the desired effect, no need - # to update last_profit_update or full_profit_unlock_date - self.profit_unlocking_rate = 0 + # NOTE: only setting this to the current timestamp will turn in the desired effect, + # no need to update profit_unlocking_rate + self.full_profit_unlock_date = block.timestamp # Record the report of profit timestamp. self.strategies[strategy].last_report = block.timestamp From 61718f72f94c98a14bd5ffd7b87244872a3d4603 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Fri, 12 Jan 2024 15:10:18 -0700 Subject: [PATCH 5/7] fix: set to 0 --- contracts/VaultV3.vy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 61917a17..83e6bc51 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -1318,10 +1318,10 @@ def _process_report(strategy: address) -> (uint256, uint256): self.full_profit_unlock_date = block.timestamp + new_profit_locking_period else: - # NOTE: only setting this to the current timestamp will turn in the desired effect, + # NOTE: only setting this to the 0 will turn in the desired effect, # no need to update profit_unlocking_rate - self.full_profit_unlock_date = block.timestamp - + self.full_profit_unlock_date = 0 + # Record the report of profit timestamp. self.strategies[strategy].last_report = block.timestamp From d246ee747775bd9babe984556ffca434fefcd20f Mon Sep 17 00:00:00 2001 From: Schlag <89420541+Schlagonia@users.noreply.github.com> Date: Sat, 20 Jan 2024 20:29:39 -0700 Subject: [PATCH 6/7] build: only burn or mint (#193) * build: only burn or mint * build: target end supply * chore: comments * fix: comments * fix: strategy changes --- contracts/VaultV3.vy | 132 ++++++++---------- .../mocks/ERC4626/MockTokenizedStrategy.sol | 4 + 2 files changed, 66 insertions(+), 70 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 83e6bc51..61e88d56 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -418,25 +418,6 @@ def _total_supply() -> uint256: # Need to account for the shares issued to the vault that have unlocked. return self.total_supply - self._unlocked_shares() -@internal -def _burn_unlocked_shares(): - """ - Burns shares that have been unlocked since last update. - In case the full unlocking period has passed, it stops the unlocking. - """ - # Get the amount of shares that have unlocked - unlocked_shares: uint256 = self._unlocked_shares() - - # Update last profit time no matter what. - self.last_profit_update = block.timestamp - - # IF 0 there's nothing to do. - if unlocked_shares == 0: - return - - # Burn the shares unlocked. - self._burn_shares(unlocked_shares, self) - @view @internal def _total_assets() -> uint256: @@ -1183,9 +1164,6 @@ def _process_report(strategy: address) -> (uint256, uint256): # Make sure we have a valid strategy. assert self.strategies[strategy].activation != 0, "inactive strategy" - # Burn shares that have been unlocked since the last update - self._burn_unlocked_shares() - # Vault assesses profits using 4626 compliant interface. # NOTE: It is important that a strategies `convertToAssets` implementation # cannot be manipulated or else the vault could report incorrect gains/losses. @@ -1198,6 +1176,8 @@ def _process_report(strategy: address) -> (uint256, uint256): gain: uint256 = 0 loss: uint256 = 0 + ### Asses Gain or Loss ### + # Compare reported assets vs. the current debt. if total_assets > current_debt: # We have a gain. @@ -1205,36 +1185,41 @@ def _process_report(strategy: address) -> (uint256, uint256): else: # We have a loss. loss = unsafe_sub(current_debt, total_assets) + + ### Asses Fees and Refunds ### # For Accountant fee assessment. total_fees: uint256 = 0 total_refunds: uint256 = 0 - - accountant: address = self.accountant # If accountant is not set, fees and refunds remain unchanged. + accountant: address = self.accountant if accountant != empty(address): total_fees, total_refunds = IAccountant(accountant).report(strategy, gain, loss) + if total_refunds > 0: + # Make sure we have enough approval and enough asset to pull. + total_refunds = min(total_refunds, min(ASSET.balanceOf(accountant), ASSET.allowance(accountant, self))) + + # Total fees to charge in shares. + total_fees_shares: uint256 = 0 # For Protocol fee assessment. protocol_fee_bps: uint16 = 0 + protocol_fees_shares: uint256 = 0 protocol_fee_recipient: address = empty(address) - # `shares_to_burn` is derived from amounts that would reduce the vaults PPS. # NOTE: this needs to be done before any pps changes shares_to_burn: uint256 = 0 - total_fees_shares: uint256 = 0 - protocol_fees_shares: uint256 = 0 # Only need to burn shares if there is a loss or fees. if loss + total_fees > 0: # The amount of shares we will want to burn to offset losses and fees. - shares_to_burn += self._convert_to_shares(loss + total_fees, Rounding.ROUND_UP) + shares_to_burn = self._convert_to_shares(loss + total_fees, Rounding.ROUND_UP) - # Vault calculates the amount of shares to mint as fees before changing totalAssets / totalSupply. + # If we have fees then get the proportional amount of shares to issue. if total_fees > 0: # Get the total amount shares to issue for the fees. - total_fees_shares = self._convert_to_shares(total_fees, Rounding.ROUND_DOWN) + total_fees_shares = shares_to_burn * total_fees / (loss + total_fees) - # Get the config for this vault. + # Get the protocol fee config for this vault. protocol_fee_bps, protocol_fee_recipient = IFactory(FACTORY).protocol_fee_config() # If there is a protocol fee. @@ -1242,13 +1227,42 @@ def _process_report(strategy: address) -> (uint256, uint256): # Get the percent of fees to go to protocol fees. protocol_fees_shares = total_fees_shares * convert(protocol_fee_bps, uint256) / MAX_BPS - # Shares to lock is any amounts that would otherwise increase the vaults PPS. - newly_locked_shares: uint256 = 0 + + # Shares to lock is any amount that would otherwise increase the vaults PPS. + shares_to_lock: uint256 = 0 + profit_max_unlock_time: uint256 = self.profit_max_unlock_time + # Get the amount we will lock to avoid a PPS increase. + if gain + total_refunds > 0 and profit_max_unlock_time != 0: + shares_to_lock = self._convert_to_shares(gain + total_refunds, Rounding.ROUND_DOWN) + + # The total current supply including locked shares. + total_supply: uint256 = self.total_supply + # The total shares the vault currently owns. Both locked and unlocked. + total_locked_shares: uint256 = self.balance_of[self] + + # Get the desired end amount of shares after all accounting. + ending_supply: uint256 = total_supply + shares_to_lock - shares_to_burn - self._unlocked_shares() + + # If we will end with more shares than we have now. + if ending_supply > total_supply: + # Issue the difference. + self._issue_shares(unsafe_sub(ending_supply, total_supply), self) + + # Else we need to burn shares. + elif total_supply > ending_supply: + # Can't burn more than the vault owns. + to_burn: uint256 = min(unsafe_sub(total_supply, ending_supply), total_locked_shares) + self._burn_shares(to_burn, self) + + # Adjust the amount to lock for this period. + if shares_to_lock > shares_to_burn: + # Don't lock fees or losses. + shares_to_lock = unsafe_sub(shares_to_lock, shares_to_burn) + else: + shares_to_burn = 0 + + # Pull refunds if total_refunds > 0: - # Load `asset` to memory. - _asset: address = self.asset - # Make sure we have enough approval and enough asset to pull. - total_refunds = min(total_refunds, min(ERC20(_asset).balanceOf(accountant), ERC20(_asset).allowance(accountant, self))) # Transfer the refunded amount of asset to the vault. self._erc20_safe_transfer_from(_asset, accountant, self, total_refunds) # Update storage to increase total assets. @@ -1261,46 +1275,23 @@ def _process_report(strategy: address) -> (uint256, uint256): self.strategies[strategy].current_debt = current_debt self.total_debt += gain - profit_max_unlock_time: uint256 = self.profit_max_unlock_time - # Mint anything we are locking to the vault. - if gain + total_refunds > 0 and profit_max_unlock_time != 0: - newly_locked_shares = self._issue_shares_for_amount(gain + total_refunds, self) - - # Strategy is reporting a loss - if loss > 0: + # Or record any reported loss + elif loss > 0: current_debt = unsafe_sub(current_debt, loss) self.strategies[strategy].current_debt = current_debt self.total_debt -= loss - # NOTE: should be precise (no new unlocked shares due to above's burn of shares) - # newly_locked_shares have already been minted / transferred to the vault, so they need to be subtracted - # no risk of underflow because they have just been minted. - previously_locked_shares: uint256 = self.balance_of[self] - newly_locked_shares - - # Now that pps has updated, we can burn the shares we intended to burn as a result of losses/fees. - # NOTE: If a value reduction (losses / fees) has occurred, prioritize burning locked profit to avoid - # negative impact on price per share. Price per share is reduced only if losses exceed locked value. - if shares_to_burn > 0: - # Cant burn more than the vault owns. - shares_to_burn = min(shares_to_burn, previously_locked_shares + newly_locked_shares) - self._burn_shares(shares_to_burn, self) - - # We burn first the newly locked shares, then the previously locked shares. - shares_not_to_lock: uint256 = min(shares_to_burn, newly_locked_shares) - # Reduce the amounts to lock by how much we burned - newly_locked_shares -= shares_not_to_lock - previously_locked_shares -= (shares_to_burn - shares_not_to_lock) - # Issue shares for fees that were calculated above if applicable. if total_fees_shares > 0: # Accountant fees are (total_fees - protocol_fees). self._issue_shares(total_fees_shares - protocol_fees_shares, accountant) - if protocol_fees_shares > 0: - self._issue_shares(protocol_fees_shares, protocol_fee_recipient) + # If we also have protocol fees. + if protocol_fees_shares > 0: + self._issue_shares(protocol_fees_shares, protocol_fee_recipient) # Update unlocking rate and time to fully unlocked. - total_locked_shares: uint256 = previously_locked_shares + newly_locked_shares + total_locked_shares = self.balance_of[self] if total_locked_shares > 0: previously_locked_time: uint256 = 0 _full_profit_unlock_date: uint256 = self.full_profit_unlock_date @@ -1308,15 +1299,16 @@ def _process_report(strategy: address) -> (uint256, uint256): if _full_profit_unlock_date > block.timestamp: # There will only be previously locked shares if time remains. # We calculate this here since it will not occur every time we lock shares. - previously_locked_time = previously_locked_shares * (_full_profit_unlock_date - block.timestamp) + previously_locked_time = (total_locked_shares - shares_to_lock) * (_full_profit_unlock_date - block.timestamp) # new_profit_locking_period is a weighted average between the remaining time of the previously locked shares and the profit_max_unlock_time - new_profit_locking_period: uint256 = (previously_locked_time + newly_locked_shares * profit_max_unlock_time) / total_locked_shares + new_profit_locking_period: uint256 = (previously_locked_time + shares_to_lock * profit_max_unlock_time) / total_locked_shares # Calculate how many shares unlock per second. self.profit_unlocking_rate = total_locked_shares * MAX_BPS_EXTENDED / new_profit_locking_period # Calculate how long until the full amount of shares is unlocked. self.full_profit_unlock_date = block.timestamp + new_profit_locking_period - + # Update the last profitable report timestamp. + self.last_profit_update = block.timestamp else: # NOTE: only setting this to the 0 will turn in the desired effect, # no need to update profit_unlocking_rate @@ -1334,7 +1326,7 @@ def _process_report(strategy: address) -> (uint256, uint256): gain, loss, current_debt, - total_fees * convert(protocol_fee_bps, uint256) / MAX_BPS, + total_fees * convert(protocol_fee_bps, uint256) / MAX_BPS, # Protocol Fees total_fees, total_refunds ) diff --git a/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol b/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol index 752cd5e6..0a29cdd3 100644 --- a/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol +++ b/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol @@ -45,7 +45,11 @@ contract MockTokenizedStrategy is TokenizedStrategy { function availableDepositLimit( address ) public view virtual returns (uint256) { +<<<<<<< HEAD uint256 _totalAssets = _strategyStorage().totalAssets; +======= + uint256 _totalAssets = totalAssets(); +>>>>>>> build: only burn or mint (#193) uint256 _maxDebt = maxDebt; return _maxDebt > _totalAssets ? _maxDebt - _totalAssets : 0; } From a0d04f9fa40679316667c1f68b3681f51833ac67 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Mon, 29 Jan 2024 15:14:21 -0700 Subject: [PATCH 7/7] chore: rebase --- contracts/VaultV3.vy | 8 ++++---- contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol | 4 ---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/contracts/VaultV3.vy b/contracts/VaultV3.vy index 61e88d56..2709bf58 100644 --- a/contracts/VaultV3.vy +++ b/contracts/VaultV3.vy @@ -1186,6 +1186,7 @@ def _process_report(strategy: address) -> (uint256, uint256): # We have a loss. loss = unsafe_sub(current_debt, total_assets) + _asset: address = self.asset ### Asses Fees and Refunds ### # For Accountant fee assessment. @@ -1198,7 +1199,7 @@ def _process_report(strategy: address) -> (uint256, uint256): if total_refunds > 0: # Make sure we have enough approval and enough asset to pull. - total_refunds = min(total_refunds, min(ASSET.balanceOf(accountant), ASSET.allowance(accountant, self))) + total_refunds = min(total_refunds, min(ERC20(_asset).balanceOf(accountant), ERC20(_asset).allowance(accountant, self))) # Total fees to charge in shares. total_fees_shares: uint256 = 0 @@ -1220,7 +1221,7 @@ def _process_report(strategy: address) -> (uint256, uint256): total_fees_shares = shares_to_burn * total_fees / (loss + total_fees) # Get the protocol fee config for this vault. - protocol_fee_bps, protocol_fee_recipient = IFactory(FACTORY).protocol_fee_config() + protocol_fee_bps, protocol_fee_recipient = IFactory(self.factory).protocol_fee_config() # If there is a protocol fee. if protocol_fee_bps > 0: @@ -1239,10 +1240,9 @@ def _process_report(strategy: address) -> (uint256, uint256): total_supply: uint256 = self.total_supply # The total shares the vault currently owns. Both locked and unlocked. total_locked_shares: uint256 = self.balance_of[self] - # Get the desired end amount of shares after all accounting. ending_supply: uint256 = total_supply + shares_to_lock - shares_to_burn - self._unlocked_shares() - + # If we will end with more shares than we have now. if ending_supply > total_supply: # Issue the difference. diff --git a/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol b/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol index 0a29cdd3..752cd5e6 100644 --- a/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol +++ b/contracts/test/mocks/ERC4626/MockTokenizedStrategy.sol @@ -45,11 +45,7 @@ contract MockTokenizedStrategy is TokenizedStrategy { function availableDepositLimit( address ) public view virtual returns (uint256) { -<<<<<<< HEAD uint256 _totalAssets = _strategyStorage().totalAssets; -======= - uint256 _totalAssets = totalAssets(); ->>>>>>> build: only burn or mint (#193) uint256 _maxDebt = maxDebt; return _maxDebt > _totalAssets ? _maxDebt - _totalAssets : 0; }