53021 sc medium deposit and bridge workflow bricked by immediate share lock users cannot bridge immediately after deposit
Submitted on Aug 14th 2025 at 17:09:44 UTC by @farman1094 for Attackathon | Plume Network
Report ID: #53021
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/immunefi-team/attackathon-plume-network-nucleus-boring-vault/blob/main/src/base/Roles/TellerWithMultiAssetSupportPredicateProxy.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
There is a critical logic flaw in all the depositAndBridge* functions of the TellerWithMultiAssetSupportPredicateProxy and DexAggregatorWrapperWithPredicateProxy contracts. When a user calls the deposit function, their newly minted shares are immediately locked by the share-lock mechanism, preventing their subsequent transfer. Later, when the bridge logic checks the lock time (via beforeTransfer), the check triggers and causes a revert — making it impossible to complete the deposit-and-bridge operation in a single transaction.
Vulnerability Details
The vulnerable code path is in DexAggregatorWrapperWithPredicateProxy.depositAndBridgeOneInch, which calls:
teller.depositAndBridge{ value: msg.value - nativeValueToWrap }(
supportedAsset, supportedAssetAmount, minimumMint, bridgeData
);Internally, this runs _erc20Deposit to mint shares for the user, followed immediately by _afterPublicDeposit, which executes:
shareUnlockTime[user] = block.timestamp + currentShareLockPeriod;This lock is set before the bridge transfer is attempted. The bridge logic then calls beforeTransfer(from), which checks:
if (shareUnlockTime[from] > block.timestamp) revert TellerWithMultiAssetSupport__SharesAreLocked();Since the shares were just locked, the transfer will always revert, making it impossible to complete the deposit-and-bridge operation in a single transaction. This logic error effectively disables the combined deposit-and-bridge feature.
Impact Details
Users will be unable to use Deposit-and-Bridge flows that expect to mint shares and immediately bridge them in the same transaction, breaking a core workflow of the protocol. The contract does not lose funds, but the feature is unusable as designed.
Proof of Concept
Step: User intends to deposit and bridge in one transaction
Alice calls
TellerWithMultiAssetSupportPredicateProxy::depositAndBridge(or the dex wrapper variant) expecting:Deposit accepted
Shares minted to Alice
Newly minted shares bridged immediately, completing a cross-chain transfer in a single transaction
Deposit Phase
The wrapper calls
teller.depositAndBridge.Inside
depositAndBridge:_erc20Depositmints shares to Alice._afterPublicDepositis immediately called:
shareUnlockTime[Alice] = block.timestamp + currentShareLockPeriod;This sets a lock on Alice's shares, preventing their transfer until the lock period expires.
Bridge Phase
The next step calls
TellerWithMultiAssetSupport::bridge.Inside bridge flow,
beforeTransfer(Alice)is called:
if (shareUnlockTime[Alice] > block.timestamp) revert TellerWithMultiAssetSupport__SharesAreLocked();Because the lock was just set, this condition is true and the call reverts.
The entire transaction fails, so deposit-and-bridge cannot complete in one transaction.
Conclusion
Immediate locking of freshly minted shares before the bridge transfer causes beforeTransfer to always revert, breaking the intended deposit-and-bridge workflow. The issue prevents the combined operation from being completed atomically; users cannot bridge immediately after deposit.
Was this helpful?