Skip to content

Commit 47c0427

Browse files
committed
test: add tests for risc0
1 parent aa871a4 commit 47c0427

16 files changed

+634
-4
lines changed

Cargo.lock

+49
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ members = [
55
"packages/fungible-token/bridge-fungible-token",
66
"packages/risc0/core",
77
"packages/risc0/host",
8+
"packages/risc0/test",
89
"packages/risc0/methods/guest"
910
]
1011

@@ -34,11 +35,13 @@ fuel-core-types = { version = "0.22.0", default-features = false }
3435
fuels = { version = "0.54.0", features = ["fuel-core-lib"] }
3536

3637
# Third-party dependencies
38+
anyhow = "1.0.75"
3739
tokio = { version = "1.32.0", features = ["rt", "macros", "full", "sync"] }
3840
hex = "0.4.3"
41+
serde = {version = "1.0.188", default-features = false}
42+
serde_json = "1.0.104"
3943

4044
# Dependendencies from risc0
41-
4245
bonsai-sdk = { git = "https://github.com/risc0/risc0", rev = "1742ef8098d246871055501a0559811c9a8fece4" }
4346
bonsai-ethereum-relay = { git = "https://github.com/risc0/risc0", rev = "1742ef8098d246871055501a0559811c9a8fece4" }
4447
risc0-build = { git = "https://github.com/risc0/risc0", rev = "1742ef8098d246871055501a0559811c9a8fece4" }

Forc.lock

+5
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,8 @@ dependencies = [
4747
"contract_message_receiver",
4848
"std",
4949
]
50+
51+
[[package]]
52+
name = "wallet"
53+
source = "member"
54+
dependencies = ["std"]

Forc.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ members = [
44
"packages/fungible-token/bridge-fungible-token",
55
"packages/message-predicates/contract-message-predicate",
66
"packages/message-predicates/contract-message-receiver",
7+
"packages/risc0/test/contracts/wallet"
78
]

packages/risc0/core/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ rust-version = { workspace = true }
1010
publish = false
1111

1212
[dependencies]
13-
anyhow = "1.0.75"
13+
anyhow = { workspace = true }
1414
bech32 = "0.9.0"
1515
bonsai-sdk = { workspace = true }
1616
bonsai-ethereum-relay = { workspace = true }
@@ -38,8 +38,8 @@ risc0-build = { workspace = true }
3838
risc0-zkvm = { workspace = true, default-features = false }
3939
parking_lot = "0.12"
4040
postcard = "1.0"
41-
serde = {version = "1.0.188", default-features = false}
42-
serde_json = "1.0.104"
41+
serde = { workspace = true, default-features = false}
42+
serde_json = { workspace = true }
4343
serde_with = "1.11"
4444
sha2 = { workspace = true }
4545
strum = "0.24"

packages/risc0/test/Cargo.toml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "test"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
anyhow = { workspace = true }
8+
fuels={version = "0.54.0", features=["std", "fuel-core-lib"]}
9+
fuel-core = { version = "0.22.0", default-features = false, features = ["relayer"] }
10+
fuel-core-chain-config = { version = "0.22.0", default-features = false }
11+
fuel-core-database = { version = "0.22.0", default-features = false }
12+
fuel-core-executor = { version = "0.22.0", default-features = false, features = ["test-helpers"] }
13+
fuel-core-importer = { version = "0.22.0", default-features = false }
14+
fuel-core-poa = { version = "0.22.0", default-features = false }
15+
fuel-core-services = { version = "0.22.0", default-features = false }
16+
fuel-core-storage = { version = "0.22.0", default-features = false, features = ["test-helpers"] }
17+
fuel-core-types = { version = "0.22.0", default-features = false, features = ["test-helpers"] }
18+
fuel-core-txpool = { version = "0.22.0", default-features = false }
19+
fuel-crypto = { version = "0.43.1", default-features = false}
20+
fuel-storage = { version = "0.43.1", default-features = false}
21+
fuel-tx = { version = "0.43.1", default-features = false, features = ["builder"]}
22+
fuel-types = { version = "0.43.1", default-features = false}
23+
fuel-vm = { version = "0.43.1", default-features = false, features = ["serde", "alloc"]}
24+
prover-core = { workspace = true }
25+
serde = { workspace = true }
26+
serde_json = { workspace = true }
27+
tokio = { workspace = true }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[project]
2+
authors = ["Fuel Labs <contact@fuel.sh>"]
3+
entry = "wallet.sw"
4+
license = "Apache-2.0"
5+
name = "wallet"
6+
7+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
contract;
2+
3+
use std::address::Address;
4+
use std::context::msg_amount;
5+
use std::call_frames::msg_asset_id;
6+
use std::asset::transfer_to_address;
7+
use std::constants::ZERO_B256;
8+
9+
abi Wallet {
10+
#[storage(read, write), payable]
11+
fn receive_funds();
12+
13+
#[storage(read, write)]
14+
fn send_funds(amount_to_send: u64, recipient_address: Address);
15+
}
16+
17+
configurable {
18+
ASSET_ID: AssetId = AssetId::from(ZERO_B256),
19+
OWNER_ADDRESS: Address = Address::from(ZERO_B256)
20+
}
21+
22+
storage {
23+
balance: u64 = 0,
24+
}
25+
26+
impl Wallet for Contract {
27+
#[storage(read, write), payable]
28+
fn receive_funds() {
29+
if msg_asset_id() == ASSET_ID {
30+
// If we received `ASSET_ID` then keep track of the balance.
31+
// Otherwise, we're receiving other native assets and don't care
32+
// about our balance of tokens.
33+
storage.balance.write(storage.balance.read() + msg_amount());
34+
}
35+
}
36+
37+
#[storage(read, write)]
38+
fn send_funds(amount_to_send: u64, recipient_address: Address) {
39+
let sender = msg_sender().unwrap();
40+
match sender {
41+
Identity::Address(addr) => assert(addr == OWNER_ADDRESS),
42+
_ => revert(0),
43+
};
44+
45+
let current_balance = storage.balance.read();
46+
assert(current_balance >= amount_to_send);
47+
48+
storage.balance.write(current_balance - amount_to_send);
49+
50+
// Note: `transfer_to_address()` is not a call and thus not an
51+
// interaction. Regardless, this code conforms to
52+
// checks-effects-interactions to avoid re-entrancy.
53+
transfer_to_address(recipient_address, ASSET_ID, amount_to_send);
54+
}
55+
}

packages/risc0/test/src/helpers.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
mod bootstrap_node;
3+
mod constants;
4+
mod snapshot;
5+
mod transactions;
6+
mod deploy;
7+
mod database;
8+
9+
pub use constants::*;
10+
pub use bootstrap_node::*;
11+
pub use snapshot::*;
12+
pub use transactions::*;
13+
pub use deploy::*;
14+
pub use database::*;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use std::time::Duration;
2+
3+
use fuel_core::{
4+
database::Database,
5+
chain_config::{ ChainConfig, StateConfig, CoinConfig },
6+
service::{Config as FuelServiceConfig, FuelService, config::Trigger} ,
7+
types::
8+
fuel_types::AssetId
9+
10+
,
11+
};
12+
use fuel_crypto::fuel_types::{Address, Bytes32};
13+
14+
use fuels::{
15+
prelude:: WalletUnlocked ,
16+
accounts::{ViewOnlyAccount, provider::Provider},
17+
};
18+
19+
use super::constants::{N_ACCOUNTS, DEFAULT_MNEMONIC_PHRASE};
20+
21+
pub async fn bootstrap1() -> anyhow::Result<(FuelService, Provider)> {
22+
let mut accounts: Vec<WalletUnlocked> = Vec::new();
23+
24+
for index in 0..N_ACCOUNTS {
25+
let wallet =
26+
WalletUnlocked::new_from_mnemonic_phrase_with_path(
27+
DEFAULT_MNEMONIC_PHRASE,
28+
None,
29+
format!("m/44'/60'/0'/0/{}", index).as_str()
30+
).expect("Could not instantiate account");
31+
32+
accounts.push(wallet);
33+
}
34+
35+
let coins: Vec<CoinConfig> = accounts
36+
.clone()
37+
.iter()
38+
.enumerate()
39+
.map(|(index, account)| {
40+
let asset_id: AssetId = Default::default();
41+
let amount = 10_000_000;
42+
43+
let mut vec_tx_id = vec![0u8; 32];
44+
vec_tx_id[31] = index as u8;
45+
let tx_id_slice: &[u8; 32] = vec_tx_id.as_slice().try_into().expect("asd");
46+
let tx_id = Bytes32::from_bytes_ref(tx_id_slice).clone();
47+
48+
CoinConfig {
49+
tx_id: Some(tx_id),
50+
output_index: Some(0),
51+
tx_pointer_block_height: Some(0.into()),
52+
tx_pointer_tx_idx: Some(0),
53+
maturity: Some(0.into()),
54+
owner: Address::new(*account.address().clone().hash),
55+
amount,
56+
asset_id,
57+
}
58+
}
59+
).collect();
60+
61+
let mut fuel_service_config = FuelServiceConfig {
62+
chain_conf: ChainConfig {
63+
initial_state: Some(StateConfig {
64+
coins: Some(coins),
65+
height: Some((0).into()),
66+
..Default::default()
67+
}),
68+
..ChainConfig::local_testnet()
69+
},
70+
block_production: Trigger::Interval { block_time: Duration::from_secs(1) },
71+
..FuelServiceConfig::local_node()
72+
};
73+
fuel_service_config.txpool.min_gas_price = 1;
74+
75+
let database = Database::in_memory();
76+
77+
let srv = FuelService::from_database(database.clone(), fuel_service_config.clone()).await.unwrap();
78+
srv.await_relayer_synced().await.unwrap();
79+
let provider = Provider::connect(srv.bound_address.to_string()).await.unwrap();
80+
81+
anyhow::Ok((srv, provider))
82+
}
83+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use fuels::accounts::{wallet::WalletUnlocked, provider::Provider};
2+
3+
pub const DEFAULT_MNEMONIC_PHRASE: &str = "test test test test test test test test test test test junk";
4+
pub const N_ACCOUNTS: u8 = 20;
5+
6+
#[allow(dead_code)]
7+
pub enum AccountName {
8+
Alice = 0,
9+
Bob = 1,
10+
Carol = 2,
11+
Dave = 3,
12+
Eve = 4,
13+
Frank = 5,
14+
Grace = 6,
15+
Heather = 7,
16+
Ivan = 8,
17+
Judy = 9,
18+
Mallory = 10,
19+
}
20+
21+
pub fn get_wallet_by_name(name: AccountName, provider: Option<Provider>) -> WalletUnlocked {
22+
let n = name as u8;
23+
let mut wallet = WalletUnlocked::new_from_mnemonic_phrase_with_path(DEFAULT_MNEMONIC_PHRASE, None, format!("m/44'/60'/0'/0/{}", n).as_str()).unwrap();
24+
25+
if provider.is_some() {
26+
wallet.set_provider(provider.unwrap());
27+
}
28+
29+
wallet
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use std::ops::Deref;
2+
3+
use fuel_core::{database::Database, types::{blockchain::block::Block, services::p2p::Transactions}};
4+
5+
pub fn get_current_block_with_txs(database: &Database) -> anyhow::Result<Block> {
6+
let block = database.get_current_block()?.unwrap();
7+
let start = block.header().height().deref().clone();
8+
let end = start + 1;
9+
let transactions =
10+
match database.get_transactions_on_blocks(start..end)? {
11+
Some(value) => {
12+
if value.len() == 1 {
13+
value.first().unwrap().clone()
14+
} else {
15+
Transactions(vec![])
16+
}
17+
}
18+
None => Transactions(vec![])
19+
};
20+
let block_with_txs =
21+
Block::try_from_executed(block.header().clone(), transactions.0).unwrap();
22+
23+
Ok(block_with_txs)
24+
}

0 commit comments

Comments
 (0)