Function: _withdraw(address caller, address receiver, address owner, uint256 assets, uint256 shares)
This internal function overrides the default ERC-4626 implementation and is invoked by the public, inherited functions withdraw
and redeem
.
Inputs
caller
Control: None.
Constraints: None.
Impact: Caller performing the withdrawal.
receiver
Control: Arbitrary.
Constraints: None.
Impact: Receiver of the withdrawal.
owner
Control: None.
Constraints: If not the sender,
caller
must have allowance.Impact: Owner of the shares to withdraw.
assets
Control: Arbitrary (when coming from
withdraw
).Constraints: None (directly, owner share balance must be sufficient).
Impact: Amount of assets to unwrap.
shares
Control: Arbitrary (when coming from
redeem
).Constraints: None (directly, owner share balance must be sufficient).
Impact: Amount of shares to unwrap.
Branches and code coverage (including function calls)
Intended branches
Spends allowance if caller is not owner.
Burns owner shares, withdraws shares from the vault, transfers
min(assets, balance)
to the receiver.
Negative behavior
Reverts if the caller does not have sufficient allowance.
Reverts if owner balance is insufficient.
Reverts if vault withdrawal fails.
Reverts if asset transfer fails (should be impossible).
Function call analysis
rootFunction -> _spendAllowance(owner, caller, shares)
What is controllable?
owner
andshares
.If return value controllable, how is it used and how can it go wrong? Not used.
What happens if it reverts, reenters, or does other unusual control flow? Reverts bubble up; reentrancy is not possible.
rootFunction -> _burn(owner, shares)
What is controllable?
owner
andshares
.If return value controllable, how is it used and how can it go wrong? Not used.
What happens if it reverts, reenters, or does other unusual control flow? Reverts bubble up; reentrancy is not possible.
rootFunction -> IVault(vault).withdraw(shares)
What is controllable?
shares
.If return value controllable, how is it used and how can it go wrong? Not used.
What happens if it reverts, reenters, or does other unusual control flow? Reverts bubble up; reentrancy is not possible (
vault
is considered trusted).
rootFunction -> IERC20Upgradeable(asset()).balanceOf(address(this))
What is controllable? Nothing.
If return value controllable, how is it used and how can it go wrong? Used to limit the maximum withdrawal.
What happens if it reverts, reenters, or does other unusual control flow? Reverts bubble up; reentrancy is not possible (
asset
is considered trusted).
rootFunction -> IERC20Upgradeable(asset()).safeTransfer(receiver, assets)
What is controllable?
receiver
andassets
.If return value controllable, how is it used and how can it go wrong? Not used.
What happens if it reverts, reenters, or does other unusual control flow? Reverts bubble up; reentrancy is not possible (
asset
is considered trusted).