Attackathon _ Fuel Network 33175 - [Smart Contract - High] Sway-lib Subtract i Logic Vulnerability
Submitted on Sat Jul 13 2024 12:16:30 GMT-0400 (Atlantic Standard Time) by @Minato7namikazi for Attackathon | Fuel Network
Report ID: #33175
Report type: Smart Contract
Report severity: High
Target: https://github.com/FuelLabs/sway-libs/tree/0f47d33d6e5da25f782fc117d4be15b7b12d291b
Impacts:
Permanent freezing of funds
Description
Vulnerability Details
within sway-libs the subtract method of the Subtract trait implementation for I8
impl core::ops::Subtract for I8 {
/// Subtract a I8 from a I8. Panics of overflow.
fn subtract(self, other: Self) -> Self {
let mut res = Self::new();
if self.underlying >= Self::indent()
&& other.underlying >= Self::indent()
{
if self.underlying > other.underlying {
res = Self::from_uint(self.underlying - other.underlying + Self::indent());
} else {
res = Self::from_uint(self.underlying - (other.underlying - Self::indent()));
}
} else if self.underlying >= Self::indent()
&& other.underlying < Self::indent()
{
res = Self::from_uint(self.underlying - Self::indent() + other.underlying);
} else if self.underlying < Self::indent()
&& other.underlying >= Self::indent()
{
res = Self::from_uint(self.underlying - (other.underlying - Self::indent()));
} else if self.underlying < Self::indent()
&& other.underlying < Self::indent()
{
if self.underlying < other.underlying {
res = Self::from_uint(other.underlying - self.underlying + Self::indent());
} else {
res = Self::from_uint(self.underlying + other.underlying - Self::indent());
}
}
res
}
}The issue is in the last branch of the conditional statement:
The problem is in the case where self.underlying < other.underlying. The current implementation is adding Self::indent() instead of subtracting it. This will result in incorrect subtraction for certain negative numbers.
As example to trigger the bug
1- let's creates two
I8values:arepresenting -2 andbrepresenting -3.2- let's performs the subtraction
a - b, which should equal 1. because -2 - (-3) = 1and while
a (representing -2) has an underlying value of 126 .. b (representing -3) has an underlying value of 125 .. and Self::indent() is 128
These values fall into the last branch of the Vulnerable if-else statement
Since 126 (self.underlying) > 125 (other.underlying), it will use the second calculation:
Plugging in the values:
Therefore, the incorrect result will have an underlying value of 123.
Check the PoC for full runnable example
Impact is loss of funds because of
Incorrect Financial Calculations: Any function that uses subtraction with I8 types, especially when dealing with negative numbers, could produce incorrect results. This could lead to logical errors in tokens & funds distribution or any computation that relies on accurate integer arithmetic.
Recommendation
This change ensures that when subtracting a larger negative number from a smaller negative number, the result is correctly calculated as a positive number.
Proof of concept
Add this PoC test in the end of the i8.sw
Last updated
Was this helpful?