Smart Security Practices From The Best
What do Lido, Red Stone, YieldNest, and Braintrust have in common? They’ve developed effective methods for improving security without drastically increasing costs. Top-tier protocol […]
The attacker acquires rewards that are generated by other users’ capital.
An attacker can unfairly gain by back-running the transfer with rewards that have not yet been included in totalAssets. This appears due to the assumption that rewards are accumulated discretely. The processAccounting function is designed to update total assets by iterating through the asset list to retrieve and calculate their balances and rates.
function processAccounting() public virtual {
VaultStorage storage vaultStorage = _getVaultStorage();
uint256 totalBaseBalance = vaultStorage.countNativeAsset ? address(this).balance : 0;
AssetStorage storage assetStorage = _getAssetStorage();
address[] memory assetList = assetStorage.list;
uint256 assetListLength = assetList.length;
uint256 baseAssetUnit = 10 ** (assetStorage.assets[asset()].decimals);
for (uint256 i = 0; i < assetListLength; i++) {
uint256 balance = IERC20(assetList[i]).balanceOf(address(this));
if (balance == 0) continue;
uint256 rate = IProvider(provider()).getRate(assetList[i]);
totalBaseBalance += balance.mulDiv(rate, baseAssetUnit, Math.Rounding.Floor);
}
_getVaultStorage().totalAssets = totalBaseBalance;
emit ProcessAccounting(block.timestamp, totalBaseBalance);
}However, the timing of the reward distribution can create an opportunity for an attacker to benefit unfairly. While the function’s purpose is to maintain correct accounting after rewards are distributed, its current design allows an arbitrage opportunity.
After the reward transfer, an attacker can make a significant deposit before the processAccounting function updates the asset rate, then withdraw immediately. Thereby unfairly sharing in the rewards generated by other users’ contributions or withdrawal fees.
In order to make this attack profitable, the increase in share price must be greater than the fee paid for such transaction. The price increase depends on the size of rewards being distributed at once, the vault’s TVL and the size of attacker’s deposit.
The following actions illustrate this issue:
processAccounting function is executed, the attacker deposits another 100 tokens, thus receiving 50 shares.processAccounting is called, the rate adjusts to 10:21.The similar arbitrage opportunity can appear when over 50% of Vault’s TVL is being withdrawn within a short period of time. The root cause is that the fee (assets) is help in the vault and increases the share price by more than the fee value.
MEDIUM – The attacker acquires rewards that are generated by other users’ capital.
processAccounting to be called at least daily (or as often as possible) to facilitate smooth reward distribution and to reduce the potential for arbitrage.processAccounting should only be available to a role that is trusted, as this will prevent an attacker from using flashloans to create a leverage.Meet Composable Security
Get throughly tested by the creators of Smart Contract Security Verification Standard
Let us help
Get throughly tested by the creators of Smart Contract Security Verification Standard