Skip to content

Commit

Permalink
Add GTF_OUTPUT_COIN_ASSET_ID and GTF_OUTPUT_COIN_TO opcode getters (
Browse files Browse the repository at this point in the history
FuelLabs#4694)

## Description

Added getters for the `GTF_OUTPUT_COIN_ASSET_ID` and
`GTF_OUTPUT_COIN_TO` opcodes. These have been highly requested by
external teams for use in predicates.

Note: The `output_asset_to()` getter currently returns a `b256` rather
than an `Identity`. This should be updated when
FuelLabs#4569 is resolved.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: bitzoic <[email protected]>
Co-authored-by: K1-R1 <[email protected]>
  • Loading branch information
3 people authored Jun 22, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 00982e4 commit 7245883
Showing 9 changed files with 175 additions and 4 deletions.
24 changes: 22 additions & 2 deletions sway-lib-std/src/outputs.sw
Original file line number Diff line number Diff line change
@@ -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;
@@ -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
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,
}
}
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ script;
use basic_storage_abi::{BasicStorage, Quad};

fn main() -> u64 {
let addr = abi(BasicStorage, 0xe685bfdc8217d28b5710a8e441cf151e3eed6749923aae8b747a7f1f51e7469a);
let addr = abi(BasicStorage, 0x03ce81c0cfbe6287ecff739afeb92cdce9c6d0d3bcb066648b2239f502b86144);
let key = 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
let value = 4242;

Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ fn main() -> bool {
let zero = b256::min();
let gas: u64 = u64::max();
let amount: u64 = 11;
let other_contract_id = ContractId::from(0x338000acdb5764cdaaf90a70b2fa73c68fed43ce2b7bdb329d361cb6b5393a43);
let other_contract_id = ContractId::from(0xbc40f25981f0778159e3dea633562c4b633ec2a37de91ca0f43005908d6df935);
let base_asset_id = BASE_ASSET_ID;

let test_contract = abi(ContextTesting, other_contract_id.into());
5 changes: 5 additions & 0 deletions test/src/sdk-harness/Forc.lock
Original file line number Diff line number Diff line change
@@ -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'
1 change: 1 addition & 0 deletions test/src/sdk-harness/Forc.toml
Original file line number Diff line number Diff line change
@@ -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",
]
13 changes: 13 additions & 0 deletions test/src/sdk-harness/test_artifacts/tx_output_predicate/Forc.lock
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 <[email protected]>"]
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);

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

@@ -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"
)
);

@@ -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::*;

@@ -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 {
@@ -746,5 +822,39 @@ mod outputs {
.unwrap();
}
}

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

let transfer_amount = 10;
predicate
.transfer(
wallet1.address(),
transfer_amount,
asset_id2,
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();
}
}
}

0 comments on commit 7245883

Please sign in to comment.