Premium claim requirement ensures safety too
In the withdraw
function, for the case where a vault has started and a fixed-side depositor is withdrawing, there is an interesting comment:
function withdraw(uint256 side) external {
require(side == FIXED || side == VARIABLE, "IS");
// Vault has not started
if (!isStarted()) {
// [...]
// Vault started and in progress
} else if (!isEnded()) {
if (side == FIXED) {
// [...]
// require that they have claimed their upfront premium to simplify this flow
uint256 bearerBalance = fixedBearerToken[msg.sender];
require(bearerBalance > 0, "NBT");
The comment indicates that the "NBT"
requirement is to simplify the workflow, so that the exit fee can be charged correctly. However, we would like to highlight that this check is an important safety check too, for a nonobvious reason.
Consider a vault that has not started yet, from which an existing fixed depositor wishes to make a withdrawal before it starts. If they naively sign a withdraw
call and broadcast it, a malicious front-runner can front-run the withdrawal with their own transactions that complete the vault. This causes the vault to start, and therefore the front-runner charges them a very large early exit fee that they were not expecting to pay.
Normally, this would be mitigated by having a different withdraw
function, or an additional argument to the function, that includes in the transaction calldata the expected state of the vault — so that a user cannot sign a withdraw
call expecting a vault state in which their withdraw does not incur fees, but it is applied to a state in a way that assumes they assented to the fee. However, the requirement that the premium be collected effectively accidentally does this, because a user who never thought the vault had started of course would not have collected the premium yet.
This issue has been acknowledged by Saffron, and a fix was implemented in commit 4f1668a0↗.