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 Output::ContractCreated transaction to Output enum #6194

Merged
merged 17 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions sway-lib-std/src/outputs.sw
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub enum Output {
Change: (),
/// A variable output.
Variable: (),
/// A contract deployment.
ContractCreated: (),
}

/// Get the type of an output at `index`.
Expand Down Expand Up @@ -66,6 +68,7 @@ pub enum Output {
/// Output::Contract => { log("The output is a contract") },
/// Output::Change => { log("The output is change") },
/// Output::Variable => { log("The output is a variable") },
/// Output::ContractCreated => { log("The output is a contract creation") },
/// };
/// }
/// ```
Expand All @@ -75,6 +78,7 @@ pub fn output_type(index: u64) -> Output {
1u8 => Output::Contract,
2u8 => Output::Change,
3u8 => Output::Variable,
4u8 => Output::ContractCreated,
_ => revert(0),
}
}
Expand Down Expand Up @@ -193,6 +197,7 @@ pub fn output_amount(index: u64) -> u64 {
r1: u64
}
},
Output::ContractCreated => revert(0),
}
}

Expand Down Expand Up @@ -257,3 +262,16 @@ pub fn output_asset_to(index: u64) -> Option<Address> {
_ => None,
}
}

impl core::ops::Eq for Output {
fn eq(self, other: Self) -> bool {
match (self, other) {
(Output::Coin, Output::Coin) => true,
(Output::Contract, Output::Contract) => true,
(Output::Change, Output::Change) => true,
(Output::Variable, Output::Variable) => true,
(Output::ContractCreated, Output::ContractCreated) => true,
_ => false,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use test_fuel_coin_abi::*;
#[cfg(experimental_new_encoding = false)]
const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c;
#[cfg(experimental_new_encoding = true)]
const FUEL_COIN_CONTRACT_ID = 0x1a88d0982d216958d18378b6784614b75868a542dc05f8cc85cf3da44268c76c;
const FUEL_COIN_CONTRACT_ID = 0xbac7800e48f9a98d99ded3bf123f0f25bf0170de6ef991a3035f76d4570c8b1e;

#[cfg(experimental_new_encoding = false)]
const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df;
Expand Down
1 change: 1 addition & 0 deletions test/src/in_language_tests/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ members = [
"test_programs/identity_inline_tests",
"test_programs/math_inline_tests",
"test_programs/option_inline_tests",
"test_programs/output_inline_tests",
"test_programs/result_inline_tests",
"test_programs/revert_inline_tests",
"test_programs/string_inline_tests",
Expand Down
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 = "output_inline_tests"

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

use std::outputs::Output;

#[test]
fn output_output_eq() {
let output_1 = Output::Coin;
let output_2 = Output::Coin;
let output_3 = Output::Contract;
let output_4 = Output::Contract;
let output_5 = Output::Change;
let output_6 = Output::Change;
let output_7 = Output::Variable;
let output_8 = Output::Variable;
let output_9 = Output::ContractCreated;
let output_10 = Output::ContractCreated;

assert(output_1 == output_2);
assert(output_3 == output_4);
assert(output_5 == output_6);
assert(output_7 == output_8);
assert(output_9 == output_10);
}

#[test]
fn output_output_neq() {
let output_1 = Output::Coin;
let output_2 = Output::Contract;
let output_3 = Output::Change;
let output_4 = Output::Variable;
let output_5 = Output::ContractCreated;

assert(output_1 != output_2);
assert(output_1 != output_3);
assert(output_1 != output_4);
assert(output_1 != output_5);

assert(output_2 != output_3);
assert(output_2 != output_4);
assert(output_2 != output_5);

assert(output_3 != output_4);
assert(output_3 != output_5);

assert(output_4 != output_5);
}
5 changes: 5 additions & 0 deletions test/src/sdk-harness/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,11 @@ name = "tx_fields"
source = "member"
dependencies = ["std"]

[[package]]
name = "tx_output_contract_creation_predicate"
source = "member"
dependencies = ["std"]

[[package]]
name = "tx_output_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 @@ -76,4 +76,5 @@ members = [
"test_artifacts/storage_vec/svec_u64",
"test_artifacts/tx_contract",
"test_artifacts/tx_output_predicate",
"test_artifacts/tx_output_contract_creation_predicate",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = "core"
source = "path+from-root-1EABD6DBC885D01E"

[[package]]
name = "std"
source = "path+from-root-1EABD6DBC885D01E"
dependencies = ["core"]

[[package]]
name = "tx_output_contract_creation_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_contract_creation_predicate"

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

use std::outputs::{Output, output_type};

fn main() -> bool {
output_type(2) == Output::ContractCreated
}
113 changes: 109 additions & 4 deletions test/src/sdk-harness/test_projects/tx_fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ use fuels::types::transaction_builders::TransactionBuilder;
use fuels::{
accounts::{predicate::Predicate, wallet::WalletUnlocked, Account},
prelude::*,
types::{input::Input as SdkInput, Bits256},
types::{input::Input as SdkInput, Bits256, output::Output as SdkOutput},
tx::StorageSlot,
};
use std::fs;

const MESSAGE_DATA: [u8; 3] = [1u8, 2u8, 3u8];
const TX_CONTRACT_BYTECODE_PATH: &str =
"test_artifacts/tx_contract/out/release/tx_contract.bin";
const TX_OUTPUT_PREDICATE_BYTECODE_PATH: &str =
"test_artifacts/tx_output_predicate/out/release/tx_output_predicate.bin";
const TX_FIELDS_PREDICATE_BYTECODE_PATH: &str =
"test_projects/tx_fields/out/release/tx_fields.bin";
const TX_CONTRACT_CREATION_PREDICATE_BYTECODE_PATH: &str =
"test_artifacts/tx_output_contract_creation_predicate/out/release/tx_output_contract_creation_predicate.bin";

abigen!(
Contract(
Expand Down Expand Up @@ -69,7 +79,7 @@ async fn get_contracts(
deployment_wallet.set_provider(provider);

let contract_id = Contract::load_from(
"test_artifacts/tx_contract/out/release/tx_contract.bin",
TX_CONTRACT_BYTECODE_PATH,
LoadConfiguration::default(),
)
.unwrap()
Expand All @@ -87,7 +97,7 @@ async fn generate_predicate_inputs(
wallet: &WalletUnlocked,
) -> (Vec<u8>, SdkInput, TxInput) {
let provider = wallet.provider().unwrap();
let predicate = Predicate::load_from("test_projects/tx_fields/out/release/tx_fields.bin")
let predicate = Predicate::load_from(TX_FIELDS_PREDICATE_BYTECODE_PATH)
.unwrap()
.with_provider(provider.clone());

Expand Down Expand Up @@ -163,7 +173,7 @@ async fn setup_output_predicate() -> (WalletUnlocked, WalletUnlocked, Predicate,
.unwrap();

let predicate = Predicate::load_from(
"test_artifacts/tx_output_predicate/out/release/tx_output_predicate.bin",
TX_OUTPUT_PREDICATE_BYTECODE_PATH,
)
.unwrap()
.with_data(predicate_data)
Expand Down Expand Up @@ -905,6 +915,101 @@ mod outputs {
assert_eq!(result.value, Output::Contract);
}

#[tokio::test]
async fn can_get_tx_output_type_for_contract_deployment() {
// Setup Wallet
let wallet = launch_custom_provider_and_get_wallets(
WalletsConfig::new(
Some(1), /* Single wallet */
Some(1), /* Single coin (UTXO) */
Some(1_000_000_000), /* Amount per coin */
),
None,
None,
)
.await
.unwrap()
.pop()
.unwrap();
let provider = wallet.try_provider().unwrap();

// Get the predicate
let predicate: Predicate = Predicate::load_from(TX_CONTRACT_CREATION_PREDICATE_BYTECODE_PATH).unwrap()
.with_provider(provider.clone());
let predicate_coin_amount = 100;

// Predicate has no funds
let predicate_balance = predicate.get_asset_balance(&provider.base_asset_id()).await.unwrap();
assert_eq!(predicate_balance, 0);

// Transfer funds to predicate
wallet
.transfer(
predicate.address(),
predicate_coin_amount,
*provider.base_asset_id(),
TxPolicies::default(),
)
.await.unwrap();

// Predicate has funds
let predicate_balance = predicate.get_asset_balance(&provider.base_asset_id()).await.unwrap();
assert_eq!(predicate_balance, predicate_coin_amount);

// Get contract ready for deployment
let binary = fs::read(TX_CONTRACT_BYTECODE_PATH).unwrap();
let salt = Salt::new([2u8; 32]);
let storage_slots = Vec::<StorageSlot>::new();
let contract = Contract::new(binary.clone(), salt, storage_slots.clone());

// Start building the transaction
let tb: CreateTransactionBuilder = CreateTransactionBuilder::prepare_contract_deployment(
binary,
contract.contract_id(),
contract.state_root(),
salt,
storage_slots,
TxPolicies::default(),
);

// Inputs
let inputs = predicate
.get_asset_inputs_for_amount(*provider.base_asset_id(), predicate_coin_amount, None)
.await.unwrap();

// Outputs
let mut outputs = wallet.get_asset_outputs_for_amount(
&wallet.address(),
*provider.base_asset_id(),
predicate_coin_amount,
);
outputs.push(SdkOutput::contract_created(contract.contract_id(), contract.state_root()));

let mut tb = tb.with_inputs(inputs).with_outputs(outputs);

wallet.add_witnesses(&mut tb).unwrap();
wallet.adjust_for_fee(&mut tb, 1).await.unwrap();

// Build transaction
let tx = tb.build(provider).await.unwrap();

// Send trandaction
provider
.send_transaction_and_await_commit(tx)
.await
.unwrap()
.check(None)
.unwrap();

// Verify contract was deployed
let instance = TxContractTest::new(contract.contract_id(), wallet.clone());
assert!(instance.methods().get_output_type(0).call().await.is_ok());

// Verify predicate funds transferred
let predicate_balance = predicate.get_asset_balance(&AssetId::default()).await.unwrap();
assert_eq!(predicate_balance, 0);
}

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