Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GTF_OUTPUT_COIN_ASSET_ID and GTF_OUTPUT_COIN_TO opcode getters #4694

Merged
merged 11 commits into from
Jun 22, 2023
24 changes: 22 additions & 2 deletions sway-lib-std/src/outputs.sw
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ use ::tx::{
Transaction,
tx_type,
};
use ::option::*;

// GTF Opcode const selectors
//
pub const GTF_OUTPUT_TYPE = 0x201;
// pub const GTF_OUTPUT_COIN_TO = 0x202;
pub const GTF_OUTPUT_COIN_TO = 0x202;
pub const GTF_OUTPUT_COIN_AMOUNT = 0x203;
// pub const GTF_OUTPUT_COIN_ASSET_ID = 0x204;
pub const GTF_OUTPUT_COIN_ASSET_ID = 0x204;
// pub const GTF_OUTPUT_CONTRACT_INPUT_INDEX = 0x205;
// pub const GTF_OUTPUT_CONTRACT_BALANCE_ROOT = 0x206;
// pub const GTF_OUTPUT_CONTRACT_STATE_ROOT = 0x207;
Expand Down Expand Up @@ -88,3 +89,22 @@ pub fn output_amount(index: u64) -> u64 {
},
}
}

/// If the output's type is `Output::Coin` return the asset ID as an `Some(id)`.
/// Otherwise, returns `None`.
pub fn output_asset_id(index: u64) -> Option<ContractId> {
match output_type(index) {
Output::Coin => Option::Some(ContractId::from(__gtf::<b256>(index, GTF_OUTPUT_COIN_ASSET_ID))),
_ => Option::None,
}
}

/// If the output's type is `Output::Coin` return the b256 as `Some(to)`.
/// Otherwise, returns `None`.
/// TODO: Update to `Identity` when https://github.com/FuelLabs/sway/issues/4569 is resolved
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
pub fn output_asset_to(index: u64) -> Option<b256> {
match output_type(index) {
Output::Coin => Option::Some(__gtf::<b256>(index, GTF_OUTPUT_COIN_TO)),
_ => Option::None,
}
}
5 changes: 5 additions & 0 deletions test/src/sdk-harness/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ name = 'tx_contract'
source = 'member'
dependencies = ['std']

[[package]]
name = 'tx_output_predicate'
source = 'member'
dependencies = ['std']

[[package]]
name = 'tx_predicate'
source = 'member'
Expand Down
1 change: 1 addition & 0 deletions test/src/sdk-harness/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ members = [
"test_artifacts/storage_vec/svec_u16",
"test_artifacts/storage_vec/svec_u64",
"test_artifacts/tx_contract",
"test_artifacts/tx_output_predicate",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-3E8AFAF9D04B1844'

[[package]]
name = 'std'
source = 'path+from-root-3E8AFAF9D04B1844'
dependencies = ['core']

[[package]]
name = 'tx_output_predicate'
source = 'member'
dependencies = ['std']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "tx_output_predicate"

[dependencies]
std = { path = "../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
predicate;

use std::outputs::{output_asset_id, output_asset_to};

fn main(index: u64, asset_id: ContractId, to: b256) -> bool {

let tx_asset_id = output_asset_id(index);
let tx_to = output_asset_to(index);

assert(tx_asset_id.is_some() && tx_asset_id.unwrap() == asset_id);
assert(tx_to.is_some() && tx_to.unwrap() == to);
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

true
}
110 changes: 110 additions & 0 deletions test/src/sdk-harness/test_projects/tx_fields/mod.rs
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use fuel_vm::fuel_tx::{
use fuels::{
accounts::{predicate::Predicate, wallet::WalletUnlocked, Account},
prelude::*,
types::Bits256,
};
use std::str::FromStr;

Expand All @@ -18,6 +19,10 @@ abigen!(
Predicate(
name = "TestPredicate",
abi = "test_projects/tx_fields/out/debug/tx_predicate-abi.json"
),
Predicate(
name = "TestOutputPredicate",
abi = "test_artifacts/tx_output_predicate/out/debug/tx_output_predicate-abi.json"
)
);

Expand Down Expand Up @@ -142,6 +147,55 @@ async fn add_message_input(tx: &mut ScriptTransaction, wallet: WalletUnlocked) {
tx.tx.inputs_mut().push(message_input);
}

async fn setup_output_predicate() -> (WalletUnlocked, WalletUnlocked, Predicate, AssetId, AssetId) {
let asset_id1 = AssetId::default();
let asset_id2 = AssetId::new([2u8; 32]);
let wallets_config = WalletsConfig::new_multiple_assets(
2,
vec![
AssetConfig {
id: asset_id1,
num_coins: 1,
coin_amount: 1_000,
},
AssetConfig {
id: asset_id2,
num_coins: 1,
coin_amount: 1_000,
},
],
);

let mut wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None).await;
let wallet1 = wallets.pop().unwrap();
let wallet2 = wallets.pop().unwrap();

let predicate_data = TestOutputPredicateEncoder::encode_data(
0,
ContractId::zeroed(),
Bits256(*wallet1.address().hash()),
);

let predicate = Predicate::load_from(
"test_artifacts/tx_output_predicate/out/debug/tx_output_predicate.bin",
)
.unwrap()
.with_data(predicate_data)
.with_provider(wallet1.try_provider().unwrap().clone());

wallet1
.transfer(predicate.address(), 100, asset_id1, TxParameters::default())
.await
.unwrap();

wallet1
.transfer(predicate.address(), 100, asset_id2, TxParameters::default())
.await
.unwrap();

(wallet1, wallet2, predicate, asset_id1, asset_id2)
}

mod tx {
use super::*;

Expand Down Expand Up @@ -726,6 +780,28 @@ mod outputs {
.unwrap();
assert_eq!(result.value, Output::Contract);
}

#[tokio::test]
async fn can_get_tx_output_details() {
let (wallet, _, predicate, asset_id, _) = setup_output_predicate().await;

let balance = predicate.get_asset_balance(&asset_id).await.unwrap();

let transfer_amount = 10;
predicate
.transfer(
wallet.address(),
transfer_amount,
asset_id,
TxParameters::default(),
)
.await
.unwrap();

let new_balance = predicate.get_asset_balance(&asset_id).await.unwrap();

assert!(balance - transfer_amount == new_balance);
}
}

mod revert {
Expand All @@ -746,5 +822,39 @@ mod outputs {
.unwrap();
}
}

#[tokio::test]
#[should_panic]
async fn fails_output_predicate_when_incorrect_asset() {
let (wallet1, _, predicate, _, asset_id) = setup_output_predicate().await;

let transfer_amount = 10;
predicate
.transfer(
wallet1.address(),
transfer_amount,
asset_id,
TxParameters::default(),
)
.await
.unwrap();
}

#[tokio::test]
#[should_panic]
async fn fails_output_predicate_when_incorrect_to() {
let (_, wallet2, predicate, asset_id1, _) = setup_output_predicate().await;

let transfer_amount = 10;
predicate
.transfer(
wallet2.address(),
transfer_amount,
asset_id1,
TxParameters::default(),
)
.await
.unwrap();
}
}
}