$err is used to store Error codes for particular operations.
If there are instructions after WDCM that check if $err is zero, and if the $err is not zero, the code flow will end early, the tx logic will be incorrect. For example, the pseudocode like:
$err is set by instructions like div, with UNSAFEMATH
WDCM is executed
$err is checked to see if its value is ZERO, if not, revert/return the tx logic
References
Add any relevant links to documentation or code
Proof of concept
Proof of Concept
please add the following code in fuel-vm/src/tests/wideint.rs and run cargo test tests::wideint::cmp_u128_one -- --nocapture
As we can see from above, err is 1, which means $err reg isn't cleared after WDCM
diff --git a/fuel-vm/src/tests/wideint.rs b/fuel-vm/src/tests/wideint.rsindex 459425f6..d85c1510 100644--- a/fuel-vm/src/tests/wideint.rs+++ b/fuel-vm/src/tests/wideint.rs@@ -96,6 +96,56 @@ fn cmp_u128( } }+#[test]+fn cmp_u128_one() {+ let a: u128 = 1;+ let b: u128 = 1;+ let mode: CompareMode = CompareMode::EQ;+ let mut ops = Vec::new();+ ops.extend(make_u128(0x20, a));+ ops.extend(make_u128(0x21, b));+ // the following 3 instruction is used to change err reg+ ops.push(op::movi(0x10, Flags::UNSAFEMATH.bits().try_into().unwrap()));+ ops.push(op::flag(0x10));+ ops.push(op::divi(0x10, RegId::ONE, 0));+ ops.push(op::wdcm_args(+ 0x22,+ 0x20,+ 0x21,+ CompareArgs {+ indirect_rhs: true,+ mode,+ },+ ));+ ops.push(op::log(0x22, 0x08, RegId::ZERO, RegId::ZERO));+ ops.push(op::ret(RegId::ONE));++ let receipts = run_script(ops);++ if let Receipt::Log { ra, rb, .. } = receipts.first().unwrap() {+ let expected = match mode {+ CompareMode::EQ => (a == b) as u64,+ CompareMode::NE => (a != b) as u64,+ CompareMode::LT => (a < b) as u64,+ CompareMode::GT => (a > b) as u64,+ CompareMode::LTE => (a <= b) as u64,+ CompareMode::GTE => (a >= b) as u64,+ CompareMode::LZC => a.leading_zeros() as u64,+ };+ assert_eq!(*ra, expected);+ println!("CompareMode::EQ: {}", CompareMode::EQ as u8);+ println!("CompareMode::NE: {}", CompareMode::NE as u8);+ println!("CompareMode::LT: {}", CompareMode::LT as u8);+ println!("CompareMode::GT: {}", CompareMode::GT as u8);+ println!("CompareMode::LTE: {}", CompareMode::LTE as u8);+ println!("CompareMode::GTE: {}", CompareMode::GTE as u8);+ println!("err: {}", *rb);+ } else {+ panic!("Expected log receipt");+ }+}++