58773 sc medium in stargate incorrect allocation cap accounting leading to unnecessary dos

Submitted on Nov 4th 2025 at 12:53:01 UTC by @aman for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58773

  • Report Type: Smart Contract

  • Report severity: Medium

  • Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/optimism/StargateEthPoolStrategy.sol

  • Impacts:

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

While allocating deposits into the Stargate strategy, the implementation removes the dust amount from the provided deposit value and only deposits the remaining amount into the strategy.However, the vault still records the full provided amount (including the removed dust) in the allocation caps mapping. As a result, the stored allocation value becomes inaccurate, leading to a situation where the system incorrectly reports that the allocation cap has been reached even though the actual deposited amount is lower.

Vulnerability Details

To understand this behavior, let’s first examine the Vault’s allocation flow: allocate -> allocateInternal

/v3-poc/lib/vault-v2/src/VaultV2.sol:570
570:     function allocateInternal(address adapter, bytes memory data, uint256 assets) internal {
571:         (bytes32[] memory ids, int256 change) = IAdapter(adapter).allocate(data, assets, msg.sig, msg.sender);
572: 
573:         for (uint256 i; i < ids.length; i++) {
574:             Caps storage _caps = caps[ids[i]];
575:             _caps.allocation = (int256(_caps.allocation) + change).toUint256();
576: 
577:             require(_caps.absoluteCap > 0, ErrorsLib.ZeroAbsoluteCap());
578:             require(_caps.allocation <= _caps.absoluteCap, ErrorsLib.AbsoluteCapExceeded());
579:             require(
580:                 _caps.relativeCap == WAD || _caps.allocation <= firstTotalAssets.mulDivDown(_caps.relativeCap, WAD),
581:                 ErrorsLib.RelativeCapExceeded()
582:             );
583:         }
584:         emit EventsLib.Allocate(msg.sender, adapter, assets, ids, change);
585:     }
586: 

At line 571, the value stored in change is added to caps.allocation. Now, let’s take a closer look at the Stargate strategy:

Here we can observe that at line 47, the dust is subtracted from the provided amount before depositing into the strategy, while at line 52, the function returns the original amount (including the dust).

By combining both code snippets, we can summarize the behavior as follows:

  1. Admin allocates: 3999999999999999996

  2. After removing dust: 3999999000000000000

  3. The _allocate function still returns 3999999999999999996, and the vault records caps.allocation = 3999999999999999996.

  4. Even after a full deallocation, the vault still shows caps.allocation = 999999999996, which corresponds exactly to the dust amount stored in step 3.

Impact Details

Due to incorrect caps.allocation calculation, the vault reports inaccurate cap values, which can cause unexpected reverts and potential DoS during allocation.

References

StargateEthPoolStrategy.sol#L46-L52arrow-up-right

Proof of Concept

Proof of Concept

Add Following file to test/strategies Dir with the name POC.t.sol :

Run With Command : forge test --match-test test_allocation_caps -vvv --decode-internal

Was this helpful?