Assessment reports>Astria Bridge>Low findings>Withdrawer address is not working in ICS20 withdrawal
Category: Coding Mistakes

Withdrawer address is not working in ICS20 withdrawal

Low Severity
Low Impact
High Likelihood

Description

The withdrawer address has permission to withdraw assets from the bridge on behalf of the bridge address.

In astria/crates/astria-sequencer/src/ibc/ics20_withdrawal.rs, the function check_stateful checks if the sender of the withdrawal action is not the bridge address; the withdrawer address should be the sender of the withdrawal action.

async fn check_stateful<S: StateReadExt + 'static>(
    &self,
    state: &S,
    from: Address,
) -> Result<()> {
    ics20_withdrawal_check_stateful_bridge_account(self, state, from).await?;
    //...
}

async fn ics20_withdrawal_check_stateful_bridge_account<S: StateReadExt + 'static>(
    action: &action::Ics20Withdrawal,
    state: &S,
    from: Address,
) -> Result<()> {
    // ...
    let bridge_address = action.bridge_address.unwrap_or(from);

    let Some(withdrawer) = state
        .get_bridge_account_withdrawer_address(&bridge_address)
        .await
        .context("failed to get bridge withdrawer")?
    else {
        bail!("bridge address must have a withdrawer address set");
    };

    ensure!(
        withdrawer == from,
        "sender does not match bridge withdrawer address; unauthorized"
    );

    Ok(())
}

But the execute method uses the from address to decrease the balance of the sender. If the sender is withdrawer address, the balance of the withdrawer address will be decreased instead of the bridge address.

async fn execute<S: StateWriteExt>(&self, state: &mut S, from: Address) -> Result<()> {
    let fee = state
        .get_ics20_withdrawal_base_fee()
        .await
        .context("failed to get ics20 withdrawal base fee")?;
    let checked_packet = withdrawal_to_unchecked_ibc_packet(self).assume_checked();

    state
        .decrease_balance(from, self.denom(), self.amount())
        .await
        .context("failed to decrease sender balance")?;

    // ...
}

Impact

When the withdrawer address tries to withdraw assets from the bridge, it does not work as expected.

Recommendations

Replace the from address with the bridge address in the execute method to decrease the balance of the bridge address instead of the withdrawer address when the sender is the withdrawer address.

Remediation

Zellic © 2025Back to top ↑