nautechsystems/nautilus_trader · error
Wrap amount must be positive
Error message
Wrap amount must be positive
What it means
BlockchainExecutionClient::wrap converts ETH into WETH by depositing amount_wei; a zero deposit is rejected because it cannot satisfy the postcondition of increasing the WETH balance and would waste gas. The library bails early on a zero U256 amount.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:678
u128::from(self.config.max_fee_per_gas_wei),
))
}
/// Wraps native currency into the wrapped native token via a WETH `deposit()`
/// transaction carrying `amount_wei` of native value.
///
/// This is an explicit operator operation; it never runs inside `submit_order`.
///
/// # Errors
///
/// Returns an error if the amount is zero, the WETH target is not a deployed ERC-20 contract,
/// the client is not connected, another transaction is in flight, no durable store is
/// configured, the WETH balance does not increase by `amount_wei`, or any RPC, policy, signing,
/// persistence, or broadcast step fails. A persistence failure after signing, or a failed
/// postcondition after finality, leaves the in-flight slot occupied.
pub async fn wrap(&mut self, amount_wei: U256) -> anyhow::Result<B256> {
if amount_wei.is_zero() {
anyhow::bail!("Wrap amount must be positive");
}
self.ensure_transaction_ready(TransactionPurpose::Wrap)?;
let calldata = WETH9::depositCall {}.abi_encode();
let executor = self.transaction_executor()?;
let included = executor
.transact(
self.weth_address,
amount_wei,
Bytes::from(calldata),
TransactionPurpose::Wrap,
None,
TransactionAuthorization::Wrap {
weth: self.weth_address,
},
)
.await?;View on GitHub (pinned to 18893faf8b)
Solutions
- Only call wrap when amount_wei > U256::zero(); skip the call otherwise
- Recompute the intended wrap amount and guard against Decimal-to-U256 truncation to zero
- Check the upstream calculation (e.g. excess balance logic) for underflow to zero
Example fix
// before
client.wrap(U256::ZERO).await?;
// after
if amount_wei.is_zero() {
return Ok(None); // nothing to wrap
}
let tx_hash = client.wrap(amount_wei).await?; Defensive patterns
Strategy: try-catch
Validate before calling
if amount_wei.is_zero() {
// skip wrap entirely
return Ok(None);
} Type guard
fn is_positive_amount(a: &U256) -> bool { !a.is_zero() } Try / catch
if amount_wei.is_zero() { return Ok(()); }
match client.wrap(amount_wei).await {
Ok(tx_hash) => info!("wrap tx: {tx_hash}"),
Err(e) => error!("wrap failed: {e}"),
} Prevention
- Guard zero amounts at the call site before wrapping
- Beware Decimal-to-U256 truncation producing 0 for sub-unit amounts
- Treat wrap as a no-op when the ETH excess is zero
When it happens
Trigger: Calling client.wrap(U256::ZERO), or wrap with an amount computed to zero (e.g. balance-minus-reserve arithmetic underflowing to 0).
Common situations: Wrapping a computed 'excess ETH' amount that is actually zero; passing a U256 default/zero initializer by mistake; converting a Decimal human amount to wei with truncation to 0.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Execution payload check batch size must be positive
- Wrap authorization does not match the transaction call
- Invalid levels: {levels}. Must be 5 or 25.
- Invalid chain name: {chain}
- Pool ID must be 32 bytes, was {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/83a59d9f3254a969.
Report an issue: GitHub.