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

feat: support all revert signals #823

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
94fb058
feat: add support for assert_eq logs
hal3e Jan 28, 2023
c9c3400
temp fix in sway with core::ops
hal3e Feb 1, 2023
b075801
implement comments
hal3e Feb 1, 2023
149f3da
merge master
hal3e Feb 2, 2023
48d2d9b
fix typo
hal3e Feb 2, 2023
743431a
merge master
hal3e Feb 3, 2023
95c30dd
Merge branch 'master' into hal3e/assert-eq
hal3e Feb 6, 2023
234f4af
add custom assert_eq until bug is fixed
hal3e Feb 6, 2023
f250e85
add custom assert_eq until bug is fixed
hal3e Feb 6, 2023
599de1a
add custom assert_eq until bug is fixed
hal3e Feb 6, 2023
75cb7aa
fix forc fmt
hal3e Feb 6, 2023
4362269
feat: support all revert signals
hal3e Feb 6, 2023
b056f19
refactor error mapping
hal3e Feb 7, 2023
695d614
Merge branch 'master' into hal3e/assert-eq
hal3e Feb 7, 2023
d435a65
Merge branch 'hal3e/assert-eq' into hal3e/support-all-err-signals
hal3e Feb 7, 2023
7baef09
merge master
hal3e Feb 7, 2023
1cbb58e
fix clippy
hal3e Feb 7, 2023
e26aca5
Merge branch 'hal3e/assert-eq' into hal3e/support-all-err-signals
hal3e Feb 7, 2023
6c344bb
fix typo
hal3e Feb 7, 2023
cf2ff32
Merge branch 'hal3e/assert-eq' into hal3e/support-all-err-signals
hal3e Feb 7, 2023
4d6266d
Merge branch 'master' into hal3e/assert-eq
hal3e Feb 8, 2023
3d94908
add issue link
hal3e Feb 8, 2023
a10e0ba
Merge branch 'hal3e/assert-eq' into hal3e/support-all-err-signals
hal3e Feb 8, 2023
9c0c2b0
Merge branch 'master' into hal3e/support-all-err-signals
hal3e Feb 8, 2023
904b5d9
use forc 0.35.0
hal3e Feb 8, 2023
d286d5e
Merge branch 'master' into hal3e/support-all-err-signals
hal3e Feb 8, 2023
0a4935f
test CI
hal3e Feb 8, 2023
20a27dc
test CI
hal3e Feb 8, 2023
627a7c7
test CI
hal3e Feb 8, 2023
97abba9
test CI
hal3e Feb 8, 2023
6ac6163
update CI
hal3e Feb 8, 2023
34a9838
update CI
hal3e Feb 8, 2023
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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ jobs:
toolchain: ${{ env.RUST_VERSION }}
# selecting a toolchain either by action or manual `rustup` calls should happen
# before the cache plugin, as it uses the current rustc version as its cache key
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
with:
prefix-key: "v1-rust"

- name: Set git config
run: |
Expand Down
4 changes: 0 additions & 4 deletions packages/fuels-core/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,4 @@ pub const BASE_ASSET_ID: AssetId = AssetId::BASE;
pub const BASE_MESSAGE_ID: MessageId = MessageId::zeroed();

pub const DEFAULT_GAS_ESTIMATION_TOLERANCE: f64 = 0.2;
pub const GAS_PRICE_FACTOR: u64 = 1_000_000_000;
pub const MAX_GAS_PER_TX: u64 = 100_000_000;

// Revert return value that indicates missing output variables
pub const FAILED_TRANSFER_TO_ADDRESS_SIGNAL: u64 = 0xffff_ffff_ffff_0001;
14 changes: 14 additions & 0 deletions packages/fuels-programs/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// Revert with this value for a failing call to `require`
pub const FAILED_REQUIRE_SIGNAL: u64 = 0xffff_ffff_ffff_0000;

/// Revert with this value for a failing call to `transfer_to_address`.
pub const FAILED_TRANSFER_TO_ADDRESS_SIGNAL: u64 = 0xffff_ffff_ffff_0001;

/// Revert with this value for a failing call to `send_message`.
pub const FAILED_SEND_MESSAGE_SIGNAL: u64 = 0xffff_ffff_ffff_0002;

/// Revert with this value for a failing call to `assert_eq`.
pub const FAILED_ASSERT_EQ_SIGNAL: u64 = 0xffff_ffff_ffff_0003;

/// Revert with this value for a failing call to `assert`.
pub const FAILED_ASSERT_SIGNAL: u64 = 0xffff_ffff_ffff_0004;
12 changes: 6 additions & 6 deletions packages/fuels-programs/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use fuel_vm::fuel_asm::PanicReason;
use fuels_core::{
abi_decoder::ABIDecoder,
abi_encoder::{ABIEncoder, UnresolvedBytes},
constants::FAILED_TRANSFER_TO_ADDRESS_SIGNAL,
parameters::{CallParameters, StorageConfiguration, TxParameters},
};
use fuels_signers::{
Expand All @@ -33,8 +32,9 @@ use fuels_types::{

use crate::{
call_response::FuelCallResponse,
constants::FAILED_TRANSFER_TO_ADDRESS_SIGNAL,
execution_script::ExecutableFuelCall,
logs::{decode_revert_error, LogDecoder},
logs::{map_revert_error, LogDecoder},
};

/// How many times to attempt to resolve missing tx dependencies.
Expand Down Expand Up @@ -682,7 +682,7 @@ where
pub async fn call(self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(&self, false)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

/// Call a contract's method on the node, in a simulated manner, meaning the state of the
Expand All @@ -693,7 +693,7 @@ where
pub async fn simulate(self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(&self, true)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

/// Simulates a call without needing to resolve the generic for the return type
Expand Down Expand Up @@ -827,7 +827,7 @@ impl MultiContractCallHandler {
pub async fn call<D: Tokenizable + Debug>(&self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(self, false)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

/// Call contract methods on the node, in a simulated manner, meaning the state of the
Expand All @@ -838,7 +838,7 @@ impl MultiContractCallHandler {
pub async fn simulate<D: Tokenizable + Debug>(&self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(self, true)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

async fn call_or_simulate<D: Tokenizable + Debug>(
Expand Down
1 change: 1 addition & 0 deletions packages/fuels-programs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod call_response;
pub mod call_utils;
pub mod constants;
pub mod contract;
pub mod execution_script;
pub mod logs;
Expand Down
50 changes: 22 additions & 28 deletions packages/fuels-programs/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ use fuels_types::{
traits::{Parameterize, Tokenizable},
};

const REQUIRE_ID: u64 = 0xffff_ffff_ffff_0000;
const ASSERT_EQ_ID: u64 = 0xffff_ffff_ffff_0003;
use crate::constants::{
FAILED_ASSERT_EQ_SIGNAL, FAILED_ASSERT_SIGNAL, FAILED_REQUIRE_SIGNAL,
FAILED_SEND_MESSAGE_SIGNAL, FAILED_TRANSFER_TO_ADDRESS_SIGNAL,
};

/// Holds a unique log ID
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -88,39 +90,37 @@ impl<'a, I: Iterator<Item = &'a Receipt>> ExtractLogIdData for I {
}
}

/// Decodes the logged type from the receipt of a `RevertTransactionError` if available
pub fn decode_revert_error(err: Error, log_decoder: &LogDecoder) -> Error {
/// Map the provided `RevertTransactionError` based on the `revert_id`.
/// If applicable, decode the logged types from the receipt.
pub fn map_revert_error(mut err: Error, log_decoder: &LogDecoder) -> Error {
if let Error::RevertTransactionError {
revert_id,
receipts,
..
} = &err
ref receipts,
ref mut reason,
} = err
{
match *revert_id {
REQUIRE_ID => return decode_require_revert(log_decoder, receipts),
ASSERT_EQ_ID => return decode_assert_eq_revert(log_decoder, receipts),
match revert_id {
FAILED_REQUIRE_SIGNAL => *reason = decode_require_revert(log_decoder, receipts),
FAILED_ASSERT_EQ_SIGNAL => *reason = decode_assert_eq_revert(log_decoder, receipts),
FAILED_ASSERT_SIGNAL => *reason = "assertion failed.".into(),
FAILED_SEND_MESSAGE_SIGNAL => *reason = "failed to send message.".into(),
FAILED_TRANSFER_TO_ADDRESS_SIGNAL => *reason = "failed transfer to address.".into(),
_ => {}
}
}
err
}

fn decode_require_revert(log_decoder: &LogDecoder, receipts: &[Receipt]) -> Error {
let reason = log_decoder
fn decode_require_revert(log_decoder: &LogDecoder, receipts: &[Receipt]) -> String {
log_decoder
.get_logs(receipts)
.ok()
.and_then(|logs| logs.last().cloned())
.unwrap_or_else(|| "Failed to decode log from require revert".to_string());

Error::RevertTransactionError {
reason,
revert_id: REQUIRE_ID,
receipts: receipts.to_owned(),
}
.unwrap_or_else(|| "failed to decode log from require revert".to_string())
}

fn decode_assert_eq_revert(log_decoder: &LogDecoder, receipts: &[Receipt]) -> Error {
let reason = log_decoder
fn decode_assert_eq_revert(log_decoder: &LogDecoder, receipts: &[Receipt]) -> String {
log_decoder
.get_logs(receipts)
.ok()
.and_then(|logs| {
Expand All @@ -131,13 +131,7 @@ fn decode_assert_eq_revert(log_decoder: &LogDecoder, receipts: &[Receipt]) -> Er
}
None
})
.unwrap_or_else(|| "Failed to decode logs from assert_eq revert".to_string());

Error::RevertTransactionError {
reason,
revert_id: ASSERT_EQ_ID,
receipts: receipts.to_owned(),
}
.unwrap_or_else(|| "failed to decode logs from assert_eq revert".to_string())
}

pub fn log_type_lookup(
Expand Down
6 changes: 3 additions & 3 deletions packages/fuels-programs/src/script_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
call_utils::{generate_contract_inputs, generate_contract_outputs},
contract::{get_decoded_output, SettableContract},
execution_script::ExecutableFuelCall,
logs::{decode_revert_error, LogDecoder},
logs::{map_revert_error, LogDecoder},
};

#[derive(Debug)]
Expand Down Expand Up @@ -197,7 +197,7 @@ where
pub async fn call(self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(&self, false)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

/// Call a script on the node, in a simulated manner, meaning the state of the
Expand All @@ -208,7 +208,7 @@ where
pub async fn simulate(self) -> Result<FuelCallResponse<D>> {
Self::call_or_simulate(&self, true)
.await
.map_err(|err| decode_revert_error(err, &self.log_decoder))
.map_err(|err| map_revert_error(err, &self.log_decoder))
}

/// Create a [`FuelCallResponse`] from call receipts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "assert_eq"
name = "asserts"

[dependencies]
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@ impl Eq for TestEnum {
}

abi TestContract {
fn assert_primitive(a: u64, b: u64);
fn assert_eq_primitive(a: u64, b: u64);
fn assert_eq_struct(test_struct: TestStruct, test_struct2: TestStruct);
fn assert_eq_enum(test_enum: TestEnum, test_enum2: TestEnum);
}

impl TestContract for Contract {
fn assert_primitive(a: u64, b: u64) {
assert(a == b);
}

fn assert_eq_primitive(a: u64, b: u64) {
assert_eq(a, b);
}
Expand Down
Loading