diff --git a/sway-lib-std/src/auth.sw b/sway-lib-std/src/auth.sw index 4551a8ca7d7..b474f2692f2 100644 --- a/sway-lib-std/src/auth.sw +++ b/sway-lib-std/src/auth.sw @@ -140,34 +140,34 @@ pub fn msg_sender() -> Result { /// } /// ``` pub fn caller_address() -> Result { - let inputs = input_count(); + let inputs = input_count().as_u64(); let mut candidate = None; - let mut i = 0u16; + let mut iter = 0; // Note: `inputs_count` is guaranteed to be at least 1 for any valid tx. - while i < inputs { - let type_of_input = input_type(i.as_u64()); + while iter < inputs { + let type_of_input = input_type(iter); match type_of_input { - Input::Coin => (), - Input::Message => (), + Some(Input::Coin) => (), + Some(Input::Message) => (), _ => { // type != InputCoin or InputMessage, continue looping. - i += 1u16; + iter += 1; continue; } } // type == InputCoin or InputMessage. let owner_of_input = match type_of_input { - Input::Coin => { - input_coin_owner(i.as_u64()) + Some(Input::Coin) => { + input_coin_owner(iter) }, - Input::Message => { - Some(input_message_sender(i.as_u64())) + Some(Input::Message) => { + input_message_sender(iter) }, _ => { // type != InputCoin or InputMessage, continue looping. - i += 1u16; + iter += 1; continue; } }; @@ -175,7 +175,7 @@ pub fn caller_address() -> Result { if candidate.is_none() { // This is the first input seen of the correct type. candidate = owner_of_input; - i += 1u16; + iter += 1; continue; } @@ -184,7 +184,7 @@ pub fn caller_address() -> Result { // at this point, so we can unwrap safely. if owner_of_input.unwrap() == candidate.unwrap() { // Owners are a match, continue looping. - i += 1u16; + iter += 1; continue; } @@ -203,11 +203,7 @@ pub fn caller_address() -> Result { /// /// # Returns /// -/// * [Address] - The address of this predicate. -/// -/// # Reverts -/// -/// * When called outside of a predicate program. +/// * [Option
] - The address of this predicate. /// /// # Examples /// @@ -215,11 +211,11 @@ pub fn caller_address() -> Result { /// use std::auth::predicate_address; /// /// fn main() { -/// let this_predicate = predicate_address(); +/// let this_predicate = predicate_address().unwrap(); /// log(this_predicate); /// } /// ``` -pub fn predicate_address() -> Address { +pub fn predicate_address() -> Option
{ // Get index of current predicate. // i3 = GM_GET_VERIFYING_PREDICATE let predicate_index = asm(r1) { @@ -230,10 +226,10 @@ pub fn predicate_address() -> Address { let type_of_input = input_type(predicate_index); match type_of_input { - Input::Coin => input_coin_owner(predicate_index).unwrap(), - Input::Message => input_message_recipient(predicate_index), + Some(Input::Coin) => input_coin_owner(predicate_index), + Some(Input::Message) => input_message_recipient(predicate_index), _ => { - revert(0) + None } } } diff --git a/sway-lib-std/src/inputs.sw b/sway-lib-std/src/inputs.sw index 622041e8d5f..00174fb194e 100644 --- a/sway-lib-std/src/inputs.sw +++ b/sway-lib-std/src/inputs.sw @@ -9,7 +9,6 @@ use ::asset_id::AssetId; use ::bytes::Bytes; use ::contract_id::ContractId; use ::option::Option::{self, *}; -use ::revert::revert; use ::tx::{ GTF_CREATE_INPUT_AT_INDEX, GTF_CREATE_INPUTS_COUNT, @@ -83,7 +82,7 @@ impl Eq for Input { /// /// # Returns /// -/// * [Input] - The type of the input at `index`. +/// * [Option] - The type of the input at `index`. /// /// # Examples /// @@ -91,16 +90,20 @@ impl Eq for Input { /// use std::inputs::input_type; /// /// fn foo() { -/// let input_type = input_type(0); +/// let input_type = input_type(0).unwrap(); /// assert(input_type == Input::Coin); /// } /// ``` -pub fn input_type(index: u64) -> Input { +pub fn input_type(index: u64) -> Option { + if index >= input_count().as_u64() { + return None + } + match __gtf::(index, GTF_INPUT_TYPE) { - 0u8 => Input::Coin, - 1u8 => Input::Contract, - 2u8 => Input::Message, - _ => revert(0), + 0u8 => Some(Input::Coin), + 1u8 => Some(Input::Contract), + 2u8 => Some(Input::Message), + _ => None, } } @@ -135,7 +138,7 @@ pub fn input_count() -> u16 { /// /// # Returns /// -/// * [u64] - The pointer of the input at `index`. +/// * [Option] - The pointer of the input at `index`. /// /// # Examples /// @@ -143,13 +146,18 @@ pub fn input_count() -> u16 { /// use std::inputs::input_pointer; /// /// fn foo() { -/// let input_pointer = input_pointer(0); +/// let input_pointer = input_pointer(0).unwrap(); /// } /// ``` -pub fn input_pointer(index: u64) -> u64 { +#[allow(dead_code)] +fn input_pointer(index: u64) -> Option { + if index >= input_count().as_u64() { + return None + } + match tx_type() { - Transaction::Script => __gtf::(index, GTF_SCRIPT_INPUT_AT_INDEX), - Transaction::Create => __gtf::(index, GTF_CREATE_INPUT_AT_INDEX), + Transaction::Script => Some(__gtf::(index, GTF_SCRIPT_INPUT_AT_INDEX)), + Transaction::Create => Some(__gtf::(index, GTF_CREATE_INPUT_AT_INDEX)), } } @@ -175,9 +183,9 @@ pub fn input_pointer(index: u64) -> u64 { /// ``` pub fn input_amount(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_AMOUNT)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_AMOUNT)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_AMOUNT)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_AMOUNT)), + _ => None, } } @@ -203,7 +211,7 @@ pub fn input_amount(index: u64) -> Option { /// ``` pub fn input_coin_owner(index: u64) -> Option
{ match input_type(index) { - Input::Coin => Some(Address::from(__gtf::(index, GTF_INPUT_COIN_OWNER))), + Some(Input::Coin) => Some(Address::from(__gtf::(index, GTF_INPUT_COIN_OWNER))), _ => None, } } @@ -227,11 +235,12 @@ pub fn input_coin_owner(index: u64) -> Option
{ /// let input_predicate_data_pointer = input_predicate_data_pointer(0); /// assert(input_predicate_data_pointer.is_some()); // Ensure the input is a coin or message input. /// } -pub fn input_predicate_data_pointer(index: u64) -> Option { +#[allow(dead_code)] +fn input_predicate_data_pointer(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_DATA)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_DATA)), + _ => None, } } @@ -243,7 +252,7 @@ pub fn input_predicate_data_pointer(index: u64) -> Option { /// /// # Returns /// -/// * [T] - The predicate data of the input at `index`. +/// * [Option] - The predicate data of the input at `index`. /// /// # Examples /// @@ -251,16 +260,19 @@ pub fn input_predicate_data_pointer(index: u64) -> Option { /// use std::inputs::input_predicate_data; /// /// fn foo() { -/// let input_predicate_data: u64 = input_predicate_data(0); +/// let input_predicate_data: u64 = input_predicate_data::(0).unwrap(); /// assert(input_predicate_data == 100); /// } /// ``` -pub fn input_predicate_data(index: u64) -> T +pub fn input_predicate_data(index: u64) -> Option where T: AbiDecode, { - use core::codec::decode_predicate_data_by_index; - decode_predicate_data_by_index::(index) + match input_type(index) { + Some(Input::Coin) => Some(core::codec::decode_predicate_data_by_index::(index)), + Some(Input::Message) => Some(core::codec::decode_predicate_data_by_index::(index)), + _ => None, + } } /// Gets the AssetId of the input at `index`. @@ -285,9 +297,9 @@ where /// ``` pub fn input_asset_id(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(AssetId::from(__gtf::(index, GTF_INPUT_COIN_ASSET_ID))), - Input::Message => Some(AssetId::base()), - Input::Contract => None, + Some(Input::Coin) => Some(AssetId::from(__gtf::(index, GTF_INPUT_COIN_ASSET_ID))), + Some(Input::Message) => Some(AssetId::base()), + _ => None, } } @@ -313,9 +325,9 @@ pub fn input_asset_id(index: u64) -> Option { /// ``` pub fn input_witness_index(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_WITNESS_INDEX)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_WITNESS_INDEX)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_WITNESS_INDEX)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_WITNESS_INDEX)), + _ => None, } } @@ -341,9 +353,9 @@ pub fn input_witness_index(index: u64) -> Option { /// ``` pub fn input_predicate_length(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_LENGTH)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_LENGTH)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_LENGTH)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_LENGTH)), + _ => None, } } @@ -367,11 +379,11 @@ pub fn input_predicate_length(index: u64) -> Option { /// assert(input_predicate_pointer.is_some()); /// } /// ``` -pub fn input_predicate_pointer(index: u64) -> Option { +fn input_predicate_pointer(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE)), + _ => None, } } @@ -383,11 +395,7 @@ pub fn input_predicate_pointer(index: u64) -> Option { /// /// # Returns /// -/// * [Bytes] - The predicate bytecode of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`. -/// -/// # Reverts -/// -/// * When the input's type is not `Input::Coin` or `Input::Message`. +/// * [Option] - The predicate bytecode of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`. /// /// # Examples /// @@ -395,23 +403,24 @@ pub fn input_predicate_pointer(index: u64) -> Option { /// use std::inputs::input_predicate; /// /// fn foo() { -/// let input_predicate = input_predicate(0); +/// let input_predicate = input_predicate(0).unwrap(); /// assert(input_predicate.len() != 0); /// } /// ``` -pub fn input_predicate(index: u64) -> Bytes { +pub fn input_predicate(index: u64) -> Option { let wrapped = input_predicate_length(index); if wrapped.is_none() { - revert(0); - }; + return None + } + let length = wrapped.unwrap(); - let new_ptr = alloc_bytes(length); match input_predicate_pointer(index) { Some(d) => { + let new_ptr = alloc_bytes(length); d.copy_bytes_to(new_ptr, length); - Bytes::from(raw_slice::from_parts::(new_ptr, length)) + Some(Bytes::from(raw_slice::from_parts::(new_ptr, length))) }, - None => revert(0), + None => None, } } @@ -437,14 +446,12 @@ pub fn input_predicate(index: u64) -> Bytes { /// ``` pub fn input_predicate_data_length(index: u64) -> Option { match input_type(index) { - Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA_LENGTH)), - Input::Message => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH)), - Input::Contract => None, + Some(Input::Coin) => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA_LENGTH)), + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH)), + _ => None, } } -// Coin Inputs - /// Gets the sender of the input message at `index`. /// /// # Arguments @@ -453,7 +460,7 @@ pub fn input_predicate_data_length(index: u64) -> Option { /// /// # Returns /// -/// * [Address] - The sender of the input message at `index`, if the input's type is `Input::Message`. +/// * [Option
] - The sender of the input message at `index`, if the input's type is `Input::Message`. /// /// # Examples /// @@ -461,12 +468,15 @@ pub fn input_predicate_data_length(index: u64) -> Option { /// use std::inputs::input_message_sender; /// /// fn foo() { -/// let input_message_sender = input_message_sender(0); +/// let input_message_sender = input_message_sender(0).unwrap(); /// assert(input_message_sender != Address::zero()); /// } /// ``` -pub fn input_message_sender(index: u64) -> Address { - Address::from(__gtf::(index, GTF_INPUT_MESSAGE_SENDER)) +pub fn input_message_sender(index: u64) -> Option
{ + match input_type(index) { + Some(Input::Message) => Some(Address::from(__gtf::(index, GTF_INPUT_MESSAGE_SENDER))), + _ => None, + } } /// Gets the recipient of the input message at `index`. @@ -477,7 +487,7 @@ pub fn input_message_sender(index: u64) -> Address { /// /// # Returns /// -/// * [Address] - The recipient of the input message at `index`, if the input's type is `Input::Message`. +/// * [Option
] - The recipient of the input message at `index`, if the input's type is `Input::Message`. /// /// # Examples /// @@ -485,12 +495,15 @@ pub fn input_message_sender(index: u64) -> Address { /// use std::inputs::input_message_recipient; /// /// fn foo() { -/// let input_message_recipient = input_message_recipient(0); +/// let input_message_recipient = input_message_recipient(0).unwrap(); /// assert(input_message_recipient != Address::zero()); /// } /// ``` -pub fn input_message_recipient(index: u64) -> Address { - Address::from(__gtf::(index, GTF_INPUT_MESSAGE_RECIPIENT)) +pub fn input_message_recipient(index: u64) -> Option
{ + match input_type(index) { + Some(Input::Message) => Some(Address::from(__gtf::(index, GTF_INPUT_MESSAGE_RECIPIENT))), + _ => None, + } } /// Gets the nonce of input message at `index`. @@ -513,8 +526,11 @@ pub fn input_message_recipient(index: u64) -> Address { /// assert(input_message_nonce != b256::zero()); /// } /// ``` -pub fn input_message_nonce(index: u64) -> b256 { - __gtf::(index, GTF_INPUT_MESSAGE_NONCE) +pub fn input_message_nonce(index: u64) -> Option { + match input_type(index) { + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_NONCE)), + _ => None, + } } /// Gets the length of the input message at `index`. @@ -525,7 +541,7 @@ pub fn input_message_nonce(index: u64) -> b256 { /// /// # Returns /// -/// * [u64] - The length of the input message at `index`, if the input's type is `Input::Message`. +/// * [Option] - The length of the input message at `index`, if the input's type is `Input::Message`. /// /// # Examples /// @@ -533,12 +549,15 @@ pub fn input_message_nonce(index: u64) -> b256 { /// use std::inputs::input_message_length; /// /// fn foo() { -/// let input_message_length = input_message_length(0); +/// let input_message_length = input_message_length(0).unwrap(); /// assert(input_message_length != 0_u64); /// } /// ``` -pub fn input_message_data_length(index: u64) -> u64 { - __gtf::(index, GTF_INPUT_MESSAGE_DATA_LENGTH) +pub fn input_message_data_length(index: u64) -> Option { + match input_type(index) { + Some(Input::Message) => Some(__gtf::(index, GTF_INPUT_MESSAGE_DATA_LENGTH)), + _ => None, + } } /// Gets the data of the input message at `index`. @@ -550,11 +569,7 @@ pub fn input_message_data_length(index: u64) -> u64 { /// /// # Returns /// -/// * [Bytes] - The data of the input message at `index`, if the input's type is `Input::Message`. -/// -/// # Reverts -/// -/// * When the input's type is not `Input::Message`. +/// * [Option] - The data of the input message at `index`, if the input's type is `Input::Message`. /// /// # Examples /// @@ -562,21 +577,21 @@ pub fn input_message_data_length(index: u64) -> u64 { /// use std::inputs::input_message_data; /// /// fn foo() { -/// let input_message_data = input_message_data(0, 0); +/// let input_message_data = input_message_data(0, 0).unwrap(); /// assert(input_message_data.len() != 0); /// } /// ``` -pub fn input_message_data(index: u64, offset: u64) -> Bytes { - assert(valid_input_type(index, Input::Message)); - let data = __gtf::(index, GTF_INPUT_MESSAGE_DATA); - let data_with_offset = data.add_uint_offset(offset); - let length = input_message_data_length(index); - let new_ptr = alloc_bytes(length); - - data_with_offset.copy_bytes_to(new_ptr, length); - Bytes::from(raw_slice::from_parts::(new_ptr, length)) -} +pub fn input_message_data(index: u64, offset: u64) -> Option { + match input_type(index) { + Some(Input::Message) => { + let data = __gtf::(index, GTF_INPUT_MESSAGE_DATA); + let data_with_offset = data.add_uint_offset(offset); + let length = input_message_data_length(index).unwrap(); + let new_ptr = alloc_bytes(length); -fn valid_input_type(index: u64, expected_type: Input) -> bool { - input_type(index) == expected_type + data_with_offset.copy_bytes_to(new_ptr, length); + Some(Bytes::from(raw_slice::from_parts::(new_ptr, length))) + }, + _ => None, + } } diff --git a/test/src/sdk-harness/test_artifacts/auth_predicate/src/main.sw b/test/src/sdk-harness/test_artifacts/auth_predicate/src/main.sw index 6541dc66529..16268669f3e 100644 --- a/test/src/sdk-harness/test_artifacts/auth_predicate/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/auth_predicate/src/main.sw @@ -3,5 +3,9 @@ predicate; use std::auth::predicate_address; fn main(address: Address) -> bool { - address == predicate_address() + let result = match predicate_address() { + Some(address) => address, + None => return false, + }; + address == result } diff --git a/test/src/sdk-harness/test_artifacts/tx_contract/src/main.sw b/test/src/sdk-harness/test_artifacts/tx_contract/src/main.sw index 5755298265c..1be7402bf12 100644 --- a/test/src/sdk-harness/test_artifacts/tx_contract/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/tx_contract/src/main.sw @@ -34,18 +34,16 @@ abi TxContractTest { fn get_tx_id() -> b256; fn get_tx_script_bytecode_hash() -> b256; - fn get_input_type(index: u64) -> Input; - fn get_tx_input_pointer(index: u64) -> u64; - fn get_input_coin_owner(index: u64) -> Address; - fn get_input_amount(index: u64) -> u64; - fn get_tx_input_predicate_data_pointer(index: u64) -> u64; - fn get_input_message_sender(index: u64) -> Address; - fn get_input_message_recipient(index: u64) -> Address; - fn get_input_message_nonce(index: u64) -> b256; - fn get_input_witness_index(index: u64) -> u16; - fn get_input_message_data_length(index: u64) -> u64; - fn get_input_predicate_length(index: u64) -> u64; - fn get_input_predicate_data_length(index: u64) -> u64; + fn get_input_type(index: u64) -> Option; + fn get_input_coin_owner(index: u64) -> Option
; + fn get_input_amount(index: u64) -> Option; + fn get_input_message_sender(index: u64) -> Option
; + fn get_input_message_recipient(index: u64) -> Option
; + fn get_input_message_nonce(index: u64) -> Option; + fn get_input_witness_index(index: u64) -> Option; + fn get_input_message_data_length(index: u64) -> Option; + fn get_input_predicate_length(index: u64) -> Option; + fn get_input_predicate_data_length(index: u64) -> Option; fn get_input_message_data(index: u64, offset: u64, expected: [u8; 3]) -> bool; fn get_input_predicate(index: u64, bytecode: Vec) -> bool; @@ -113,46 +111,41 @@ impl TxContractTest for Contract { fn get_tx_script_bytecode_hash() -> b256 { tx_script_bytecode_hash() } - fn get_tx_input_pointer(index: u64) -> u64 { - input_pointer(index) - } - fn get_input_type(index: u64) -> Input { + fn get_input_type(index: u64) -> Option { input_type(index) } - fn get_input_coin_owner(index: u64) -> Address { - input_coin_owner(index).unwrap() + fn get_input_coin_owner(index: u64) -> Option
{ + input_coin_owner(index) } - fn get_input_amount(index: u64) -> u64 { - input_amount(index).unwrap() + fn get_input_amount(index: u64) -> Option { + input_amount(index) } - fn get_tx_input_predicate_data_pointer(index: u64) -> u64 { - asm(r1: input_predicate_data_pointer(index).unwrap()) { - r1: u64 - } - } - fn get_input_message_sender(index: u64) -> Address { + fn get_input_message_sender(index: u64) -> Option
{ input_message_sender(index) } - fn get_input_message_recipient(index: u64) -> Address { + fn get_input_message_recipient(index: u64) -> Option
{ input_message_recipient(index) } - fn get_input_message_nonce(index: u64) -> b256 { + fn get_input_message_nonce(index: u64) -> Option { input_message_nonce(index) } - fn get_input_witness_index(index: u64) -> u16 { - input_witness_index(index).unwrap() + fn get_input_witness_index(index: u64) -> Option { + input_witness_index(index) } - fn get_input_message_data_length(index: u64) -> u64 { + fn get_input_message_data_length(index: u64) -> Option { input_message_data_length(index) } - fn get_input_predicate_length(index: u64) -> u64 { - input_predicate_length(index).unwrap() + fn get_input_predicate_length(index: u64) -> Option { + input_predicate_length(index) } - fn get_input_predicate_data_length(index: u64) -> u64 { - input_predicate_data_length(index).unwrap() + fn get_input_predicate_data_length(index: u64) -> Option { + input_predicate_data_length(index) } fn get_input_message_data(index: u64, offset: u64, expected: [u8; 3]) -> bool { - let data = input_message_data(index, offset); + let data = match input_message_data(index, offset) { + Some(b) => b, + None => return false, + }; let mut expected_data_bytes = Bytes::new(); @@ -163,7 +156,11 @@ impl TxContractTest for Contract { } fn get_input_predicate(index: u64, bytecode: Vec) -> bool { - let code = input_predicate(index); + let code = match input_predicate(index) { + Some(code) => code, + None => return false, + }; + assert(input_predicate_length(index).unwrap() == bytecode.len()); let mut i = 0; while i < bytecode.len() { diff --git a/test/src/sdk-harness/test_projects/auth/mod.rs b/test/src/sdk-harness/test_projects/auth/mod.rs index bb40b3f68b6..e04d817a18b 100644 --- a/test/src/sdk-harness/test_projects/auth/mod.rs +++ b/test/src/sdk-harness/test_projects/auth/mod.rs @@ -196,7 +196,7 @@ async fn can_get_predicate_address() { // Setup predicate. let hex_predicate_address: &str = - "0xddd0922a689f07a4b08b589c38e1542a19b6002212c648e79f675a2d1d887971"; + "0x421ed9a7b208036e67dc95b7f0c0ae085f5c0b3ee55af9719d146ea6a59e0716"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); let predicate_bech32_address = Bech32Address::from(predicate_address); @@ -322,7 +322,7 @@ async fn when_incorrect_predicate_address_passed() { async fn can_get_predicate_address_in_message() { // Setup predicate address. let hex_predicate_address: &str = - "0xddd0922a689f07a4b08b589c38e1542a19b6002212c648e79f675a2d1d887971"; + "0x421ed9a7b208036e67dc95b7f0c0ae085f5c0b3ee55af9719d146ea6a59e0716"; let predicate_address = Address::from_str(hex_predicate_address).expect("failed to create Address from string"); let predicate_bech32_address = Bech32Address::from(predicate_address); diff --git a/test/src/sdk-harness/test_projects/predicate_data_simple/src/main.sw b/test/src/sdk-harness/test_projects/predicate_data_simple/src/main.sw index 873051e2cc8..c803a2d790c 100644 --- a/test/src/sdk-harness/test_projects/predicate_data_simple/src/main.sw +++ b/test/src/sdk-harness/test_projects/predicate_data_simple/src/main.sw @@ -3,7 +3,10 @@ predicate; use std::inputs::input_predicate_data; fn main() -> bool { - let received: u32 = input_predicate_data::(0); + let received: u32 = match input_predicate_data::(0) { + Some(data) => data, + None => return false, + }; let expected: u32 = 12345; received == expected diff --git a/test/src/sdk-harness/test_projects/predicate_data_struct/src/main.sw b/test/src/sdk-harness/test_projects/predicate_data_struct/src/main.sw index fa1136e3e62..2a977490521 100644 --- a/test/src/sdk-harness/test_projects/predicate_data_struct/src/main.sw +++ b/test/src/sdk-harness/test_projects/predicate_data_struct/src/main.sw @@ -8,6 +8,9 @@ struct Validation { } fn main() -> bool { - let validation: Validation = input_predicate_data::(0); + let validation: Validation = match input_predicate_data::(0) { + Some(data) => data, + None => return false, + }; validation.total_complete == 100 && validation.has_account } diff --git a/test/src/sdk-harness/test_projects/tx_fields/mod.rs b/test/src/sdk-harness/test_projects/tx_fields/mod.rs index e5a48b37058..12251d42da6 100644 --- a/test/src/sdk-harness/test_projects/tx_fields/mod.rs +++ b/test/src/sdk-harness/test_projects/tx_fields/mod.rs @@ -485,29 +485,6 @@ mod tx { mod inputs { use super::*; - mod revert { - use super::*; - - mod contract { - use super::*; - - #[tokio::test] - #[should_panic(expected = "Revert(0)")] - async fn fails_to_get_predicate_data_pointer_from_input_contract() { - let (contract_instance, _, _, _) = get_contracts(true).await; - let call_params = CallParameters::default(); - contract_instance - .methods() - .get_tx_input_predicate_data_pointer(0) - .call_params(call_params) - .unwrap() - .call() - .await - .unwrap(); - } - } - } - mod success { use super::*; @@ -521,7 +498,7 @@ mod inputs { .call() .await .unwrap(); - assert_eq!(result.value, Input::Contract); + assert_eq!(result.value, Some(Input::Contract)); let result = contract_instance .methods() @@ -529,7 +506,16 @@ mod inputs { .call() .await .unwrap(); - assert_eq!(result.value, Input::Coin); + assert_eq!(result.value, Some(Input::Coin)); + + // Assert invalid index returns None + let result = contract_instance + .methods() + .get_input_type(2) + .call() + .await + .unwrap(); + assert_eq!(result.value, None); } #[tokio::test] @@ -543,7 +529,17 @@ mod inputs { .await .unwrap(); - assert_eq!(result.value, default_amount); + assert_eq!(result.value, Some(default_amount)); + + // Assert invalid index returns None + let result = contract_instance + .methods() + .get_input_amount(2) + .call() + .await + .unwrap(); + + assert_eq!(result.value, None); } #[tokio::test] @@ -557,7 +553,17 @@ mod inputs { .await .unwrap(); - assert_eq!(owner_result.value, deployment_wallet.address().into()); + assert_eq!(owner_result.value, Some(deployment_wallet.address().into())); + + // Assert invalid index returns None + let result = contract_instance + .methods() + .get_input_coin_owner(2) + .call() + .await + .unwrap(); + + assert_eq!(result.value, None); } #[tokio::test] @@ -589,6 +595,16 @@ mod inputs { .take_receipts_checked(None) .unwrap(); assert_eq!(receipts[1].data(), Some(&[1u8][..])); + + // Assert invalid index returns None + let result = contract_instance + .methods() + .get_input_predicate(3, predicate_bytes.clone()) + .call() + .await + .unwrap(); + + assert_eq!(result.value, false); } mod message { @@ -627,7 +643,17 @@ mod inputs { .take_receipts_checked(None) .unwrap(); - assert_eq!(receipts[1].data().unwrap(), *message.sender.hash()); + assert_eq!(receipts[1].data().unwrap()[8..40], *message.sender.hash()); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_message_sender(0) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -663,7 +689,17 @@ mod inputs { .take_receipts_checked(None) .unwrap(); - assert_eq!(receipts[1].data().unwrap(), recipient.as_slice()); + assert_eq!(receipts[1].data().unwrap()[8..40], *recipient.as_slice()); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_message_recipient(0) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -700,7 +736,17 @@ mod inputs { .take_receipts_checked(None) .unwrap(); - assert_eq!(receipts[1].data().unwrap(), nonce.as_slice()); + assert_eq!(receipts[1].data().unwrap()[8..40], *nonce.as_slice()); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_message_nonce(0) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -713,7 +759,17 @@ mod inputs { .await .unwrap(); - assert_eq!(result.value, 0); + assert_eq!(result.value, Some(0)); + + // Assert none returned when not a valid index + let none_result = contract_instance + .methods() + .get_input_witness_index(3) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -748,7 +804,17 @@ mod inputs { .take_receipts_checked(None) .unwrap(); - assert_eq!(receipts[1].data(), Some(&[0, 0, 0, 0, 0, 0, 0, 3][..])); + assert_eq!(receipts[1].data(), Some(&[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3][..])); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_message_data_length(0) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -784,7 +850,17 @@ mod inputs { .unwrap(); let len = predicate_bytecode.len() as u64; - assert_eq!(receipts[1].data(), Some(len.to_be_bytes().as_slice())); + assert_eq!(receipts[1].data().unwrap()[8..16], *len.to_be_bytes().as_slice()); + + // Assert none returned when index is invalid + let none_result = contract_instance + .methods() + .get_input_predicate_length(3) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -818,7 +894,17 @@ mod inputs { .take_receipts_checked(None) .unwrap(); - assert_eq!(receipts[1].data(), Some(0u64.to_le_bytes().as_slice())); + assert_eq!(receipts[1].data().unwrap()[8..16], *0u64.to_le_bytes().as_slice()); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_predicate_data_length(0) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, None); } #[tokio::test] @@ -855,6 +941,16 @@ mod inputs { .unwrap(); assert_eq!(receipts[1].data(), Some(&[1][..])); + + // Assert none returned when transaction type is not a message + let none_result = contract_instance + .methods() + .get_input_message_data(3, 0, MESSAGE_DATA) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, false); } #[tokio::test] @@ -866,7 +962,7 @@ mod inputs { let handler = contract_instance .methods() - .get_input_predicate(3, predicate_bytecode); + .get_input_predicate(3, predicate_bytecode.clone()); let mut builder = handler.transaction_builder().await.unwrap(); @@ -888,6 +984,16 @@ mod inputs { .unwrap(); assert_eq!(receipts[1].data(), Some(1u8.to_le_bytes().as_slice())); + + // Assert none returned when index is invalid + let none_result = contract_instance + .methods() + .get_input_predicate(3, predicate_bytecode) + .call() + .await + .unwrap(); + + assert_eq!(none_result.value, false); } } }