Skip to content

Commit

Permalink
Add error message on system contract (#1494)
Browse files Browse the repository at this point in the history
* Add error message on system contract

* fmt

* Small fix

* PR comments

* After-merge fix

* fmt + dependency fix

* Rollback version

* Fix unused imports

* Fix lint error
  • Loading branch information
Ifropc authored Jul 29, 2024
1 parent 8fe3e98 commit 4a7349f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 20 additions & 1 deletion cmd/soroban-cli/src/commands/contract/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ use std::str::FromStr;
use std::{fmt::Debug, fs, io};

use clap::{arg, command, Parser};
use stellar_xdr::curr::{ContractDataEntry, ContractExecutable, ScVal};

use crate::commands::contract::fetch::Error::{ContractIsStellarAsset, UnexpectedContractToken};
use crate::commands::{global, NetworkRunnable};
use crate::config::{
self, locator,
network::{self, Network},
};
use crate::utils::rpc::get_remote_wasm_from_hash;
use crate::{
rpc::{self, Client},
Pwd,
Expand Down Expand Up @@ -64,6 +67,13 @@ pub enum Error {
Network(#[from] network::Error),
#[error("cannot create contract directory for {0:?}")]
CannotCreateContractDir(PathBuf),
#[error("unexpected contract data {0:?}")]
UnexpectedContractToken(ContractDataEntry),
#[error(
"cannot fetch wasm for contract because the contract is \
a network built-in asset contract that does not have a downloadable code binary"
)]
ContractIsStellarAsset(),
}

impl From<Infallible> for Error {
Expand Down Expand Up @@ -126,6 +136,15 @@ impl NetworkRunnable for Cmd {
client
.verify_network_passphrase(Some(&network.network_passphrase))
.await?;
Ok(client.get_remote_wasm(&contract_id).await?)
let data_entry = client.get_contract_data(&contract_id).await?;
if let ScVal::ContractInstance(contract) = &data_entry.val {
return match &contract.executable {
ContractExecutable::Wasm(hash) => {
Ok(get_remote_wasm_from_hash(&client, hash).await?)
}
ContractExecutable::StellarAsset => Err(ContractIsStellarAsset()),
};
}
return Err(UnexpectedContractToken(data_entry));
}
}
3 changes: 2 additions & 1 deletion cmd/soroban-cli/src/get_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use soroban_spec_tools::contract as contract_spec;
use crate::commands::global;
use crate::config::{self, data, locator, network};
use crate::rpc;
use crate::utils::rpc::get_remote_wasm_from_hash;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -65,7 +66,7 @@ pub async fn get_remote_contract_spec(
if let Ok(entries) = data::read_spec(&hash_str) {
entries
} else {
let raw_wasm = client.get_remote_wasm_from_hash(hash).await?;
let raw_wasm = get_remote_wasm_from_hash(&client, &hash).await?;
let res = contract_spec::Spec::new(&raw_wasm)?;
let res = res.spec;
if global_args.map_or(true, |a| !a.no_cache) {
Expand Down
23 changes: 23 additions & 0 deletions cmd/soroban-cli/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ pub fn contract_id_hash_from_asset(
Ok(Hash(Sha256::digest(preimage_xdr).into()))
}

pub mod rpc {
use soroban_env_host::xdr;
use soroban_rpc::{Client, Error};
use stellar_xdr::curr::{Hash, LedgerEntryData, LedgerKey, Limits, ReadXdr};

pub async fn get_remote_wasm_from_hash(client: &Client, hash: &Hash) -> Result<Vec<u8>, Error> {
let code_key = LedgerKey::ContractCode(xdr::LedgerKeyContractCode { hash: hash.clone() });
let contract_data = client.get_ledger_entries(&[code_key]).await?;
let entries = contract_data.entries.unwrap_or_default();
if entries.is_empty() {
return Err(Error::NotFound(
"Contract Code".to_string(),
hex::encode(hash),
));
}
let contract_data_entry = &entries[0];
match LedgerEntryData::from_xdr_base64(&contract_data_entry.xdr, Limits::none())? {
LedgerEntryData::ContractCode(xdr::ContractCodeEntry { code, .. }) => Ok(code.into()),
scval => Err(Error::UnexpectedContractCodeDataType(scval)),
}
}
}

pub mod parsing {

use regex::Regex;
Expand Down

0 comments on commit 4a7349f

Please sign in to comment.