Skip to content

Commit

Permalink
pre-audit works (#48)
Browse files Browse the repository at this point in the history
* test(e2e): cw to evm working

* chore: add error more detail information

* chore: clippy

* test: use osmo hrp

* chore: too many arguments

* feat(core): polish

* ignore profraw

* readme

---------

Co-authored-by: hashableric <hashableric@gmail.com>
  • Loading branch information
byeongsu-hong and hashableric committed Oct 18, 2023
1 parent 7dd4265 commit 31d4938
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ Cargo.lock

.DS_Store
.idea/

**/*.profraw
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,37 @@

> This project is under active development...!
## Prerequisites

- rust (wasm32-wasm32-unknown target)
- go 1.20 or higher
- grcov

## How to build

```bash
cargo build

cargo wasm
```

## How to test

```bash
# testing
cargo test

# coverage
export RUSTFLAGS="-Cinstrument-coverage"
export LLVM_PROFILE_FILE="eddy-%p-%m.profraw"

cargo build

cargo test

grcov . -s . --binary-path ./target/debug/ -t lcov --branch --ignore-not-existing -o ./target/debug/coverage/
```

## Deploy Sequence

1. Deploy [Mailbox](./contracts/core/mailbox)
Expand Down
58 changes: 30 additions & 28 deletions contracts/core/mailbox/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,38 @@ fn get_required_value(
None => return Ok((None, None)),
};

match info.funds.len() {
0 => Ok((None, None)),
1 => {
let received = &info.funds[0];

deps.api.debug(&format!(
"mailbox::dispatch: required: {:?}, received: {:?}",
required, received
));

ensure_eq!(
&received.denom,
&required.denom,
PaymentError::ExtraDenom(received.clone().denom)
);

if received.amount <= required.amount {
return Ok((Some(received.clone()), None));
}
if info.funds.is_empty() {
return Ok((None, None));
}

Ok((
Some(required.clone()),
Some(coin(
(received.amount - required.amount).u128(),
required.denom,
)),
))
}
_ => Err(PaymentError::MultipleDenoms {}.into()),
if info.funds.len() > 1 {
return Err(PaymentError::MultipleDenoms {}.into());
}

let received = &info.funds[0];

deps.api.debug(&format!(
"mailbox::dispatch: required: {:?}, received: {:?}",
required, received
));

ensure_eq!(
&received.denom,
&required.denom,
PaymentError::ExtraDenom(received.clone().denom)
);

if received.amount <= required.amount {
return Ok((Some(received.clone()), None));
}

Ok((
Some(required.clone()),
Some(coin(
(received.amount - required.amount).u128(),
required.denom,
)),
))
}

pub fn set_default_ism(
Expand Down
9 changes: 7 additions & 2 deletions contracts/igps/core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use cosmwasm_std::Uint256;

#[derive(thiserror::Error, Debug, PartialEq)]
pub enum ContractError {
#[error("{0}")]
Expand All @@ -12,8 +14,11 @@ pub enum ContractError {
#[error("unauthorized")]
Unauthorized {},

#[error("insufficient funds")]
InsufficientFunds {},
#[error("insufficient funds: needed {gas_needed:?}, but only received {received:?}")]
InsufficientFunds {
received: Uint256,
gas_needed: Uint256,
},

#[error("gas oracle not found for {0}")]
GasOracleNotFound(u32),
Expand Down
8 changes: 7 additions & 1 deletion contracts/igps/core/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@ pub fn pay_for_gas(
let gas_token = GAS_TOKEN.load(deps.storage)?;
let received = Uint256::from(cw_utils::must_pay(&info, &gas_token)?);
let gas_needed = quote_gas_price(deps.storage, &deps.querier, dest_domain, gas_amount)?;
ensure!(received >= gas_needed, ContractError::InsufficientFunds {});
ensure!(
received >= gas_needed,
ContractError::InsufficientFunds {
received,
gas_needed,
}
);

let payment_gap = Uint128::from_str(&(received - gas_needed).to_string())?;

Expand Down
13 changes: 5 additions & 8 deletions contracts/isms/multisig/src/execute/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ mod test {
const ADDR1_VAULE: &str = "addr1";
const ADDR2_VAULE: &str = "addr2";

const VAL_HRP: &str = "osmo";
const VALIDATOR_ADDR: &str = "osmo1q28uzwtvvvlkz6k84gd7flu576x2l2ry9506p5";
const VALIDATOR_PUBKEY: &str =
"033a59bbc4cb7f1e7110541e54be1ff8de6abb75fe16adaea242c52d0d7a384baf";
Expand Down Expand Up @@ -192,8 +193,7 @@ mod test {

mock_owner(deps.as_mut().storage, owner.clone());

HRP.save(deps.as_mut().storage, &"data".to_string())
.unwrap();
HRP.save(deps.as_mut().storage, &VAL_HRP.into()).unwrap();

let msg = MsgValidatorSet {
domain: 1u32,
Expand Down Expand Up @@ -238,8 +238,7 @@ mod test {
let validator: String = VALIDATOR_ADDR.to_string();
let domain: u32 = 1;

HRP.save(deps.as_mut().storage, &"data".to_string())
.unwrap();
HRP.save(deps.as_mut().storage, &VAL_HRP.into()).unwrap();

mock_owner(deps.as_mut().storage, owner.clone());
let msg = MsgValidatorSet {
Expand Down Expand Up @@ -291,8 +290,7 @@ mod test {

mock_owner(deps.as_mut().storage, owner);

HRP.save(deps.as_mut().storage, &"data".to_string())
.unwrap();
HRP.save(deps.as_mut().storage, &VAL_HRP.into()).unwrap();

let msg = vec![
MsgValidatorSet {
Expand Down Expand Up @@ -324,8 +322,7 @@ mod test {
let validator_pubkey = HexBinary::from_hex(VALIDATOR_PUBKEY).unwrap();
mock_owner(deps.as_mut().storage, owner.clone());

HRP.save(deps.as_mut().storage, &"data".to_string())
.unwrap();
HRP.save(deps.as_mut().storage, &VAL_HRP.into()).unwrap();

let msg = vec![
MsgValidatorSet {
Expand Down
1 change: 1 addition & 0 deletions integration-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ripemd.workspace = true
hex-literal.workspace = true
ibcx-test-utils.workspace = true

hpl-ownable.workspace = true
hpl-ism-multisig.workspace = true
hpl-interface.workspace = true

Expand Down
1 change: 1 addition & 0 deletions integration-test/tests/contracts/cw/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn instantiate<'a, M: Serialize, R: Runner<'a>>(
.address)
}

#[allow(clippy::too_many_arguments)]
pub fn deploy_core<'a, R: Runner<'a>>(
wasm: &Wasm<'a, R>,
owner: &SigningAccount,
Expand Down
2 changes: 1 addition & 1 deletion integration-test/tests/contracts/cw/igp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Igp {
owner,
)?;

if self.oracle_configs.len() > 0 {
if !self.oracle_configs.is_empty() {
wasm.execute(
&igp_oracle,
&igp::oracle::ExecuteMsg::SetRemoteGasDataConfigs {
Expand Down
21 changes: 4 additions & 17 deletions integration-test/tests/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,28 +88,15 @@ async fn test_mailbox_cw_to_evm() -> eyre::Result<()> {
&[TestValidators::new(DOMAIN_EVM, 5, 3)],
&[RemoteGasDataConfig {
remote_domain: DOMAIN_EVM,
token_exchange_rate: Uint128::from(1u128 * 10u128.pow(4)),
gas_price: Uint128::from(1u128 * 10u128.pow(9)),
token_exchange_rate: Uint128::from(10u128.pow(4)),
gas_price: Uint128::from(10u128.pow(9)),
}],
)?;

// TODO: leave this until Neutron supports test-tube properly
// // init Neutron env
// let ntrn_app = OsmosisTestApp::new();
// let ntrn = cw::setup_env(
// &ntrn_app,
// |app, coins| app.init_account(coins).unwrap(),
// None::<&str>,
// "neutron",
// DOMAIN_NTRN,
// &[TestValidators::new(DOMAIN_EVM, 5, 3)],
// )?;

// init Anvil env
let anvil1 = eth::setup_env(DOMAIN_EVM).await?;

let _ = send_msg(&anvil1, &osmo).await?;
// let _ = send_msg(&anvil1, &ntrn).await?;

Ok(())
}
Expand All @@ -127,8 +114,8 @@ async fn test_mailbox_evm_to_cw() -> eyre::Result<()> {
&[TestValidators::new(DOMAIN_EVM, 5, 3)],
&[RemoteGasDataConfig {
remote_domain: DOMAIN_EVM,
token_exchange_rate: Uint128::from(1u128 * 10u128.pow(4)),
gas_price: Uint128::from(1u128 * 10u128.pow(9)),
token_exchange_rate: Uint128::from(10u128.pow(4)),
gas_price: Uint128::from(10u128.pow(9)),
}],
)?;

Expand Down
64 changes: 60 additions & 4 deletions integration-test/tests/validator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use cosmwasm_std::{Binary, HexBinary};
use ethers::types::Address;
use cosmwasm_std::{
testing::{mock_dependencies, mock_info},
Binary, HexBinary,
};
use ethers::types::{Address, H160};
use ethers::utils::hex::FromHex;
use hpl_interface::{
ism::multisig::ValidatorSet,
types::{bech32_encode, pub_to_addr, MessageIdMultisigIsmMetadata},
ism::multisig::{ThresholdSet, ValidatorSet},
types::{bech32_encode, pub_to_addr, Message, MessageIdMultisigIsmMetadata},
};
use ibcx_test_utils::{addr, gen_bz};
use k256::{
ecdsa::{RecoveryId, SigningKey, VerifyingKey},
elliptic_curve::rand_core::OsRng,
Expand Down Expand Up @@ -161,3 +165,55 @@ impl TestValidators {
})
}
}

#[test]
fn test_validator() {
let hrp = "osmo";
let owner = addr("owner");
let validators = TestValidators::new(2, 5, 3);

let mut deps = mock_dependencies();

hpl_ownable::initialize(deps.as_mut().storage, &owner).unwrap();

hpl_ism_multisig::state::HRP
.save(deps.as_mut().storage, &hrp.to_string())
.unwrap();

hpl_ism_multisig::execute::enroll_validators(
deps.as_mut(),
mock_info(owner.as_str(), &[]),
validators.to_set(hrp),
)
.unwrap();

hpl_ism_multisig::execute::set_threshold(
deps.as_mut(),
mock_info(owner.as_str(), &[]),
ThresholdSet {
domain: validators.domain,
threshold: validators.threshold,
},
)
.unwrap();

let mut message: Message = gen_bz(100).into();
message.origin_domain = validators.domain;

let message_id = message.id();

let metadata = validators
.make_metadata(
H160::from_slice(gen_bz(20).as_slice()),
gen_bz(32).as_slice().try_into().unwrap(),
1,
message_id.as_slice().try_into().unwrap(),
true,
)
.unwrap();

let res =
hpl_ism_multisig::query::verify_message(deps.as_ref(), metadata.into(), message.into())
.unwrap();
assert!(res.verified);
}
6 changes: 5 additions & 1 deletion packages/interface/src/types/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ pub struct MessageIdMultisigIsmMetadata {

impl From<MessageIdMultisigIsmMetadata> for HexBinary {
fn from(v: MessageIdMultisigIsmMetadata) -> Self {
v.origin_merkle_tree
let mut origin_merkle_tree = [0u8; 32];
origin_merkle_tree[32 - v.origin_merkle_tree.len()..]
.copy_from_slice(&v.origin_merkle_tree);

origin_merkle_tree
.to_vec()
.iter()
.chain(v.merkle_root.to_vec().iter())
Expand Down

0 comments on commit 31d4938

Please sign in to comment.