Skip to content

Commit

Permalink
Add Ethereum dest validation
Browse files Browse the repository at this point in the history
  • Loading branch information
mappum committed Sep 29, 2024
1 parent 41fc736 commit ddcd5ee
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 37 deletions.
115 changes: 78 additions & 37 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,26 @@ impl InnerApp {
connection,
address,
} => {
// TODO
self.ethereum
.network(*network)?
.connection((*connection).into())?;
if *address == [0; 20] {
return Err(Error::App("Invalid Ethereum address".to_string()));
}
}
#[cfg(feature = "ethereum")]
Dest::EthCall { .. } => {
// TODO
Dest::EthCall {
network,
connection,
fallback_address,
..
} => {
self.ethereum
.network(*network)?
.connection((*connection).into())?;
if *fallback_address == [0; 20] {
return Err(Error::App("Invalid Ethereum address".to_string()));
}
}
Dest::Bitcoin { data } => self.bitcoin.validate_withdrawal(data, amount)?,
Dest::Stake {
Expand Down Expand Up @@ -450,8 +465,65 @@ impl InnerApp {
Ok(())
}

pub fn credit_dest(&mut self, dest: Dest, nbtc: Coin<Nbtc>, sender: Identity) -> Result<()> {
dbg!(dest.to_string());
fn try_credit_dest(
&mut self,
dest: Dest,
mut coins: Coin<Nbtc>,
sender: Identity,
) -> Result<()> {
let mut succeeded = false;
let amount = coins.amount;
if self.validate_dest(&dest, amount, sender).is_ok() {
if let Err(e) = self.credit_dest(dest.clone(), coins.take(amount)?, sender) {
log::debug!("Error crediting transfer: {:?}", e);
// TODO: ensure no errors can happen after mutating
// state in credit_dest since state won't be reverted

// Assume coins passed into credit_dest are burnt,
// replace them in `coins`
coins.give(Coin::mint(amount))?;
} else {
succeeded = true;
}
}

// Handle failures
if !succeeded {
log::debug!(
"Failed to credit transfer to {} (amount: {}, sender: {})",
dest,
amount,
sender,
);

match sender {
Identity::NativeAccount { address } => {
self.bitcoin.accounts.deposit(address, coins)?;
}
Identity::EthAccount {

Check failure on line 503 in src/app.rs

View workflow job for this annotation

GitHub Actions / clippy

no variant named `EthAccount` found for enum `app::Identity`

error[E0599]: no variant named `EthAccount` found for enum `app::Identity` --> src/app.rs:503:27 | 503 | Identity::EthAccount { | ^^^^^^^^^^ variant not found in `app::Identity` ... 1951 | pub enum Identity { | ----------------- variant `EthAccount` not found here
network,
connection,
address,
} => {
self.ethereum

Check failure on line 508 in src/app.rs

View workflow job for this annotation

GitHub Actions / clippy

no field `ethereum` on type `&mut app::InnerApp`

error[E0609]: no field `ethereum` on type `&mut app::InnerApp` --> src/app.rs:508:26 | 508 | self.ethereum | ^^^^^^^^ unknown field | = note: available fields are: `accounts`, `staking`, `airdrop`, `community_pool`, `incentive_pool` ... and 12 others
.network_mut(network)?
.connection_mut(connection.into())?
.transfer(address.into(), coins)?;
}
_ => {}
}
}

Ok(())
}

fn credit_dest(&mut self, dest: Dest, nbtc: Coin<Nbtc>, sender: Identity) -> Result<()> {
log::debug!(
"Crediting dest: {} (amount: {}, sender: {})",
&dest,
nbtc.amount,
&sender
);
match dest {
Dest::NativeAccount { address } => self.bitcoin.accounts.deposit(address, nbtc)?,
Dest::Ibc { data: dest } => dest.transfer(nbtc, &mut self.bitcoin, &mut self.ibc)?,
Expand Down Expand Up @@ -854,38 +926,7 @@ mod abci {

let pending_nbtc_transfers = self.bitcoin.take_pending()?;
for (dest, coins, sender) in pending_nbtc_transfers {
if self.validate_dest(&dest, coins.amount, sender).is_ok() {
let amount = coins.amount;
if let Err(e) = self.credit_dest(dest.clone(), coins, sender) {
// TODO: this will catch all errors, we only want to catch validation errors
log::debug!(
"Failed to credit transfer to {} (amount: {}, sender: {})",
dest,
amount,
sender,
);
log::debug!("{:?}", e);
}
} else {
log::debug!("Invalid transfer to {}, {}", dest, coins.amount);

match sender {
Identity::NativeAccount { address } => {
self.bitcoin.accounts.deposit(address, coins)?;
}
Identity::EthAccount {
network,
connection,
address,
} => {
self.ethereum
.network_mut(network)?
.connection_mut(connection.into())?
.transfer(address.into(), coins)?;
}
_ => {}
}
}
self.try_credit_dest(dest, coins, sender)?;
}

let external_outputs = if self.bitcoin.should_push_checkpoint()? {
Expand Down
14 changes: 14 additions & 0 deletions src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ impl Ethereum {
Ok(to_sign)
}

pub fn network(&self, network: u32) -> Result<Ref<Network>> {
Ok(self
.networks
.get(network)?
.ok_or_else(|| Error::App("Unknown network".to_string()))?)
}

pub fn network_mut(&mut self, network: u32) -> Result<ChildMut<u32, Network>> {
Ok(self
.networks
Expand Down Expand Up @@ -335,6 +342,13 @@ impl Network {
Ok(pending)
}

pub fn connection(&self, connection: Address) -> Result<Ref<Connection>> {
Ok(self
.connections
.get(connection)?
.ok_or_else(|| Error::App("Unknown connection".to_string()))?)
}

pub fn connection_mut(&mut self, connection: Address) -> Result<ChildMut<Address, Connection>> {
Ok(self
.connections
Expand Down

0 comments on commit ddcd5ee

Please sign in to comment.