Users have the possibility to stake their vault shares to accumulate fee distributions from the market making engine.
They can stake by calling VaultRouterBranch::stake
. The problem is that accumulateActor
function doesn't save the amount of rewards user accumulated.
function accumulateActor(Data storage self, bytes32 actorId) internal returns (SD59x18 valueChange) {
Actor storage actor = self.actor[actorId];
return _updateLastValuePerShare(self, actor, ud60x18(actor.shares));
}
function _updateLastValuePerShare(
Data storage self,
Actor storage actor,
UD60x18 newActorShares
)
private
returns (SD59x18 valueChange)
{
valueChange = _getActorValueChange(self, actor);
actor.lastValuePerShare = newActorShares.eq(UD60x18_ZERO) ? int256(0) : self.valuePerShare;
}
function _getActorValueChange(
Data storage self,
Actor storage actor
)
private
view
returns (SD59x18 valueChange)
{
SD59x18 deltaValuePerShare = sd59x18(self.valuePerShare).sub(sd59x18(actor.lastValuePerShare));
valueChange = deltaValuePerShare.mul(ud60x18(actor.shares).intoSD59x18());
}
pragma solidity 0.8.25;
import { ERC20, IERC20 } from "@openzeppelin/token/ERC20/ERC20.sol";
import { Base_Test } from "test/Base.t.sol";
import { Errors } from "@zaros/utils/Errors.sol";
import { Vault } from "@zaros/market-making/leaves/Vault.sol";
import { IDexAdapter } from "@zaros/utils/interfaces/IDexAdapter.sol";
import {console} from "forge-std/console.sol";
contract StakingRewards_doNotAccumulate_Test is Base_Test {
VaultConfig wBtcVaultConfig;
VaultConfig wStEthVaultConfig;
PerpMarketCreditConfig wBtcMarket;
PerpMarketCreditConfig arbMarket;
function setUp() public virtual override {
Base_Test.setUp();
changePrank({ msgSender: users.owner.account });
createVaults(marketMakingEngine, INITIAL_VAULT_ID, FINAL_VAULT_ID, true, address(perpsEngine));
configureMarkets();
changePrank({ msgSender: users.naruto.account });
_localSetup();
}
function test_stakingRewards_doNotAccumulate() public {
console.log("=== test execution started ===");
address naruto = users.naruto.account;
address weth = marketMakingEngine.workaround_getWethAddress();
uint128 narutoDeposit = 1e8;
deal({ token: address(wBtc), to: naruto, give: narutoDeposit });
_prank(naruto);
IERC20(wBtcVaultConfig.asset).approve(address(marketMakingEngine), narutoDeposit);
marketMakingEngine.deposit(wBtcVaultConfig.vaultId, narutoDeposit, 0, "", false);
uint256 vaultShares = IERC20(wBtcVaultConfig.indexToken).balanceOf(naruto);
IERC20(wBtcVaultConfig.indexToken).approve(address(marketMakingEngine), vaultShares);
marketMakingEngine.stake(wBtcVaultConfig.vaultId, uint128(vaultShares / 2));
deal({ token: weth, to: address(perpsEngine), give: 0.2 * 1e18 });
_prank(address(perpsEngine));
IERC20(weth).approve(address(marketMakingEngine), 0.2 * 1e18);
marketMakingEngine.receiveMarketFee(
wBtcMarket.marketId,
weth,
0.01 * 1e18
);
_prank(naruto);
marketMakingEngine.stake(wBtcVaultConfig.vaultId, uint128(vaultShares / 2));
_prank(naruto);
vm.expectRevert(Errors.NoFeesToClaim.selector);
marketMakingEngine.claimFees(wBtcVaultConfig.vaultId);
}
function _localSetup() internal {
wBtcVaultConfig = vaultsConfig[WBTC_CORE_VAULT_ID];
wStEthVaultConfig = vaultsConfig[WSTETH_CORE_VAULT_ID];
uint256[] memory vaultIds = new uint256[]();
vaultIds[0] = wBtcVaultConfig.vaultId;
wBtcMarket = perpMarketsCreditConfig[BTC_PERP_MARKET_CREDIT_CONFIG_ID];
arbMarket = perpMarketsCreditConfig[ARB_PERP_MARKET_CREDIT_CONFIG_ID];
uint256[] memory marketIds = new uint256[]();
marketIds[0] = wBtcMarket.marketId;
marketIds[1] = arbMarket.marketId;
_prank(users.owner.account );
marketMakingEngine.connectVaultsAndMarkets(marketIds, vaultIds);
}
function _prank(address account) internal {
vm.stopPrank();
vm.startPrank(account);
}
}
Users will loose acumulated rewards.