Skip to content

Commit ed32473

Browse files
committed
fix: use value equality for 256-bit zero and -1 checks
1 parent d5b6d67 commit ed32473

File tree

1 file changed

+143
-6
lines changed

1 file changed

+143
-6
lines changed

soroban-sdk/src/num.rs

Lines changed: 143 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,7 @@ impl U256 {
206206
pub const BITS: u32 = 256;
207207

208208
fn is_zero(&self) -> bool {
209-
const ZERO: U256Val = U256Val::from_u32(0);
210-
self.val.as_val().get_payload() == ZERO.as_val().get_payload()
209+
*self == U256::from_u32(&self.env, 0)
211210
}
212211

213212
pub fn from_u32(env: &Env, u: u32) -> Self {
@@ -440,13 +439,11 @@ impl I256 {
440439
pub const BITS: u32 = 256;
441440

442441
fn is_zero(&self) -> bool {
443-
const ZERO: I256Val = I256Val::from_i32(0);
444-
self.val.as_val().get_payload() == ZERO.as_val().get_payload()
442+
*self == I256::from_i32(&self.env, 0)
445443
}
446444

447445
fn is_neg_one(&self) -> bool {
448-
const NEG_ONE: I256Val = I256Val::from_i32(-1);
449-
self.val.as_val().get_payload() == NEG_ONE.as_val().get_payload()
446+
*self == I256::from_i32(&self.env, -1)
450447
}
451448

452449
/// Returns the minimum value of I256 (-2^255).
@@ -850,6 +847,61 @@ mod test {
850847
assert_eq!(u3.rem_euclid(&u4), U256::from_u32(&env, 3));
851848
}
852849

850+
#[test]
851+
fn test_u256_checked_arith() {
852+
let env = Env::default();
853+
854+
let u1 = U256::from_u32(&env, 6);
855+
let u2 = U256::from_u32(&env, 3);
856+
assert_eq!(u1.checked_add(&u2), Some(U256::from_u32(&env, 9)));
857+
assert_eq!(u1.checked_sub(&u2), Some(U256::from_u32(&env, 3)));
858+
assert_eq!(u1.checked_mul(&u2), Some(U256::from_u32(&env, 18)));
859+
assert_eq!(u1.checked_div(&u2), Some(U256::from_u32(&env, 2)));
860+
assert_eq!(u1.checked_pow(2), Some(U256::from_u32(&env, 36)));
861+
assert_eq!(u1.checked_shl(2), Some(U256::from_u32(&env, 24)));
862+
assert_eq!(u1.checked_shr(1), Some(U256::from_u32(&env, 3)));
863+
864+
let u3 = U256::from_u32(&env, 7);
865+
let u4 = U256::from_u32(&env, 4);
866+
assert_eq!(u3.checked_rem_euclid(&u4), Some(U256::from_u32(&env, 3)));
867+
}
868+
869+
#[test]
870+
fn test_u256_checked_arith_overflow() {
871+
let env = Env::default();
872+
873+
let zero = U256::from_u32(&env, 0);
874+
let one = U256::from_u32(&env, 1);
875+
let two = U256::from_u32(&env, 2);
876+
let max = U256::from_parts(&env, u64::MAX, u64::MAX, u64::MAX, u64::MAX);
877+
assert_eq!(max.checked_add(&one), None);
878+
assert_eq!(zero.checked_sub(&one), None);
879+
assert_eq!(max.checked_mul(&two), None);
880+
assert_eq!(one.checked_div(&zero), None);
881+
assert_eq!(max.checked_pow(2), None);
882+
assert_eq!(one.checked_shl(256), None);
883+
assert_eq!(one.checked_shr(256), None);
884+
assert_eq!(one.checked_rem_euclid(&zero), None);
885+
886+
let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
887+
let one_from_parts = U256::from_parts(&env, 0, 0, 0, 1);
888+
assert_eq!(one.checked_div(&zero_from_parts), None);
889+
assert_eq!(zero.checked_sub(&one_from_parts), None);
890+
}
891+
892+
#[test]
893+
fn test_u256_is_zero() {
894+
let env = Env::default();
895+
896+
let zero = U256::from_u32(&env, 0);
897+
let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
898+
let non_zero = U256::from_u32(&env, 1);
899+
900+
assert!(zero.is_zero());
901+
assert!(zero_from_parts.is_zero());
902+
assert!(!non_zero.is_zero());
903+
}
904+
853905
#[test]
854906
fn test_i256_arith() {
855907
let env = Env::default();
@@ -868,4 +920,89 @@ mod test {
868920
let u4 = I256::from_i32(&env, 4);
869921
assert_eq!(u3.rem_euclid(&u4), I256::from_i32(&env, 1));
870922
}
923+
924+
#[test]
925+
fn test_i256_checked_arith() {
926+
let env = Env::default();
927+
928+
let i1 = I256::from_i32(&env, -6);
929+
let i2 = I256::from_i32(&env, 3);
930+
assert_eq!(i1.checked_add(&i2), Some(I256::from_i32(&env, -3)));
931+
assert_eq!(i1.checked_sub(&i2), Some(I256::from_i32(&env, -9)));
932+
assert_eq!(i1.checked_mul(&i2), Some(I256::from_i32(&env, -18)));
933+
assert_eq!(i1.checked_div(&i2), Some(I256::from_i32(&env, -2)));
934+
assert_eq!(i1.checked_pow(2), Some(I256::from_i32(&env, 36)));
935+
assert_eq!(i1.checked_shl(2), Some(I256::from_i32(&env, -24)));
936+
assert_eq!(i1.checked_shr(1), Some(I256::from_i32(&env, -3)));
937+
938+
let u3 = I256::from_i32(&env, -7);
939+
let u4 = I256::from_i32(&env, 4);
940+
assert_eq!(u3.checked_rem_euclid(&u4), Some(I256::from_i32(&env, 1)));
941+
}
942+
943+
#[test]
944+
fn test_i256_checked_arith_overflow() {
945+
let env = Env::default();
946+
947+
let zero = I256::from_i32(&env, 0);
948+
let one = I256::from_i32(&env, 1);
949+
let negative_one = I256::from_i32(&env, -1);
950+
let two = I256::from_i32(&env, 2);
951+
let max = I256::from_parts(&env, i64::MAX, u64::MAX, u64::MAX, u64::MAX);
952+
let min = I256::from_parts(&env, i64::MIN, 0, 0, 0);
953+
assert_eq!(max.checked_add(&one), None);
954+
assert_eq!(min.checked_sub(&one), None);
955+
assert_eq!(max.checked_mul(&two), None);
956+
assert_eq!(one.checked_div(&zero), None);
957+
assert_eq!(min.checked_div(&negative_one), None);
958+
assert_eq!(max.checked_pow(2), None);
959+
assert_eq!(one.checked_shl(256), None);
960+
assert_eq!(one.checked_shr(256), None);
961+
assert_eq!(one.checked_rem_euclid(&zero), None);
962+
963+
let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
964+
let one_from_parts = I256::from_parts(&env, 0, 0, 0, 1);
965+
assert_eq!(one.checked_div(&zero_from_parts), None);
966+
assert_eq!(min.checked_sub(&one_from_parts), None);
967+
}
968+
969+
#[test]
970+
fn test_i256_is_zero() {
971+
let env = Env::default();
972+
973+
let zero = I256::from_i32(&env, 0);
974+
let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
975+
let non_zero = I256::from_i32(&env, 1);
976+
977+
assert!(zero.is_zero());
978+
assert!(zero_from_parts.is_zero());
979+
assert!(!non_zero.is_zero());
980+
}
981+
982+
#[test]
983+
fn test_i256_is_neg_one() {
984+
let env = Env::default();
985+
986+
let negative_one = I256::from_i32(&env, -1);
987+
let negative_one_from_parts = I256::from_parts(&env, -1, u64::MAX, u64::MAX, u64::MAX);
988+
let negative_two = I256::from_i32(&env, -2);
989+
990+
assert!(negative_one.is_neg_one());
991+
assert!(negative_one_from_parts.is_neg_one());
992+
assert!(!negative_two.is_neg_one());
993+
}
994+
995+
#[test]
996+
fn test_i256_is_div_overflow() {
997+
let env = Env::default();
998+
999+
let zero = I256::from_i32(&env, 0);
1000+
let negative_one = I256::from_i32(&env, -1);
1001+
let min = I256::min_value(&env);
1002+
1003+
assert!(!zero.is_div_overflow(&negative_one));
1004+
1005+
assert!(negative_one.is_div_overflow(&zero));
1006+
assert!(min.is_div_overflow(&negative_one));
1007+
}
8711008
}

0 commit comments

Comments
 (0)