Attackathon _ Fuel Network 32275 - [Smart Contract - Medium] Various Sway Libs Bugs
Submitted on Mon Jun 17 2024 08:57:19 GMT-0400 (Atlantic Standard Time) by @anatomist for Attackathon | Fuel Network
Report ID: #32275
Report type: Smart Contract
Report severity: Medium
Target: https://github.com/FuelLabs/sway-libs/tree/0f47d33d6e5da25f782fc117d4be15b7b12d291b
Impacts:
Incorrect library function behaviors
Description
Brief/Intro
sway-libs provides a lot of utility functions to help contract development. Thus its correctness is important to ensure developers don't suffer from hidden vulnerabilities. We've identified a large amount of bugs within the libraries, and will go through each bug class in this report.
Vulnerability Details
Incorrect bit width for signed_integers and fixed_point
signed_integers and fixed_pointThe
i256::bitsis incorrectly set to 128.Strictly speaking,
ifp64has ~33 bits and not 64 bits. Similarlyifp128has ~64 bits andifp256has ~129 bits
Incorrect two's complement implementation for signed_integers
signed_integersThe twos complement currently doesn't make sense. For instance, two's complement for -1i8 should be 0xff, but the implementation returns 0x81
Incorrect indent for i128 and i256
i128 and i256i128indent should be1<<127, andi256indent should be1<<255
Unnecessary subtract In UFP32::fract
UFP32::fractThe subtraction of
u32::maxinUFP32::fractwill lead to underflow andpanic
Incorrect usage of IFP::from
IFP::fromIFP::fromtreats input as raw underlying instead of integers (different fromsigned_integer). It is misused in several places
IFP::ceil overflow on values close to min
IFP::ceil overflow on values close to minIFP::ceil takesceilof underlying and then adjusts the values. Thus values near tomin` might suffer from incorrect overflow
Incorrect panic of fixed_point::round
fixed_point::roundfixed_point::roundtakes bothceil/floorand use them to derive the rounded values. Thus even if the final result falls within the valid range, function would stillpanicif eitherceiloffloordoes.
Incorrect denominator in UFP128::sqrt and UFP32::sqrt
UFP128::sqrt and UFP32::sqrtThe denominator for
UFP128::sqrtshould be1<<32instead of2<<32The denominator for
UFP32::sqrtshould be1<<8instead of1<<16
UFP::sqrt precision loss
UFP::sqrt precision lossThe implementation of
UFP::sqrtloses 1/4 of precision in terms of its size.
UFP::pow` premature overflow leads to revert
UFP::powdirectly callspowon the underlying value, which will easily overflow for values >= 1.
fixed_point::exp precision loss
fixed_point::exp precision lossUFP::expis wildly inaccurate. We haven't properly estimated to amount of precision lost. But the PoC attached should demonstrate the idea.
UFP32::exp and IFP256::exp uses incorrect taylor series
UFP32::exp and IFP256::exp uses incorrect taylor seriesUFP32::expuses the taylor series forUFP64::expIFP256::expuses the taylor series forIFP128::exp
Incorrect min for IFP
min for IFPminforIFPshould usetype::MAXas underlying value
Lack of consideration of negative zero for IFP compare functions
IFP compare functionsIFP::gtandIFP::ltdoesn't consider negative zeros. This might lead to incorrect results.IFP::non_negativedoesn't consider negative zeroes. And might returnfalsefor those.
Incorrect adjustment for IFP::ceil
IFP::ceilIFP::ceilincreasesunderlyingwhen the value is negative, while the correct implementation should be to decreaseunderlying.
Impact Details
It is hard to provide a concrete impact for library functions. But let's just say users may not be able to predict its behavior and might be caught of guard when those functions do unexpected stuff. And given the abundance of bugs, it seems extremely likely that users would run into those.
References
Incorrect bit width for signed_integers and fixed_point
signed_integers and fixed_pointhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i256.sw#L88https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L46https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L46https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L46
Incorrect two's complement implementation for signed_integers
signed_integershttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i8.sw#L398https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i16.sw#L399https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i32.sw#L398https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i64.sw#L399https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i128.sw#L423https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i256.sw#L419
Incorrect indent for i128 and i256
i128 and i256https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i128.sw#L38https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/signed_integers/i256.sw#L39
Unnecessary subtract In UFP32::fract
UFP32::fracthttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L391
Incorrect usage of IFP::from
IFP::fromhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L416https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L475https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L476https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L416https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L475https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L476https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L554
IFP::ceil overflow on values close to min
IFP::ceil overflow on values close to minhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L473https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L473https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L473
Incorrect panic of fixed_point::round
fixed_point::roundhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L443https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp64.sw#L437https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L383https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L515https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L515https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L515
Incorrect denominator in UFP128::sqrt and UFP32::sqrt
UFP128::sqrt and UFP32::sqrthttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L443https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L462
UFP::sqrt precision loss
UFP::sqrt precision losshttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L462https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp64.sw#L456https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L442
UFP::pow` premature overflow leads to revert
https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L492https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L497https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp64.sw#L487https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L450https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L452
fixed_point::exp precision loss
fixed_point::exp precision losshttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L471https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp64.sw#L465https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp128.sw#L469https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L533https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L533https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L533
UFP32::exp and IFP256::exp uses incorrect taylor series
UFP32::exp and IFP256::exp uses incorrect taylor serieshttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ufp32.sw#L475https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L537
Incorrect min for IFP
min for IFPhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L87https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L87https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L87
Lack of consideration of negative zero for IFP compare functions
IFP compare functionshttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L208https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L220https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L208https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L220https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L208https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L220https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L193https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L193https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L193
Incorrect adjustment for IFP::ceil
IFP::ceilhttps://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp64.sw#L475https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp128.sw#L475https://github.com/FuelLabs/sway-libs/blob/0f47d33d6e5da25f782fc117d4be15b7b12d291b/libs/src/fixed_point/ifp256.sw#L475
Proof of concept
Proof of Concept
Incorrect bit width for signed_integers and fixed_point
signed_integers and fixed_pointIncorrect two's complement implementation for signed_integers
signed_integersIncorrect indent for i128 and i256
i128 and i256Unnecessary subtract In UFP32::fract
UFP32::fractIncorrect usage of IFP::from
IFP::fromIFP::ceil overflow on values close to min
IFP::ceil overflow on values close to minIncorrect panic of fixed_point::round
fixed_point::roundIncorrect denominator in UFP128::sqrt and UFP32::sqrt
UFP128::sqrt and UFP32::sqrtUFP::sqrt precision loss
UFP::sqrt precision lossUFP::pow` premature overflow leads to revert
fixed_point::exp precision loss
fixed_point::exp precision lossUFP32::exp and IFP256::exp uses incorrect taylor series
UFP32::exp and IFP256::exp uses incorrect taylor seriesIncorrect min for IFP
min for IFPLack of consideration of negative zero for IFP compare functions
IFP compare functionsIncorrect adjustment for IFP::ceil
IFP::ceilLast updated
Was this helpful?