function withdrawTo(address account, IProduct product, UFixed18 amount)
notPaused
collateralInvariant(msg.sender, product)
maintenanceInvariant(msg.sender, product)
external {
    _products[product].debitAccount(msg.sender, amount);
    token.push(account, amount);

    emit Withdrawal(msg.sender, product, amount);
}
modifier maintenanceInvariant(address account, IProduct product) {
    _;

    UFixed18 maintenance = product.maintenance(account);
    UFixed18 maintenanceNext = product.maintenanceNext(account);

    if (UFixed18Lib.max(maintenance, maintenanceNext).gt(collateral(account, product)))
        revert CollateralInsufficientCollateralError();
}
function maintenanceInternal(Position memory position, IProductProvider provider) private view returns (UFixed18) {
    Fixed18 oraclePrice = provider.priceAtVersion(provider.currentVersion());
    UFixed18 notionalMax = Fixed18Lib.from(position.max()).mul(oraclePrice).abs();
    return notionalMax.mul(provider.maintenance());
}
