Boost _ Folks Finance 33981 - [Smart Contract - Low] The PythNode library process function implementation does not account for pythDataexpo being greater than PRECISION
Submitted on Sat Aug 03 2024 07:13:32 GMT-0400 (Atlantic Standard Time) by @bbl4de for Boost | Folks Finance
Report ID: #33981
Report type: Smart Contract
Report severity: Low
Target: https://testnet.snowtrace.io/address/0xA758c321DF6Cd949A8E074B22362a4366DB1b725
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
The PythNode
is supposed to support tokens with arbitrary decimals. This is not the case when the returned price's exponent is greater than PRECISION
- when the token has more than 18 decimals.
Vulnerability Details
PythNode
implements the process()
function, where the following code is responsible for adjusting decimals:
Although it takes into account that the factor
variable may be negative, it will revert in this situation because of the check in the SafeCast
library's toUint256()
function:
as we can see in the code and comment above this library function does NOT support casting from a negative int256.
Impact Details
When the PythNode
is used, it is assumed that it supports tokens with any decimals. However, because of the misuse of the SafeCast library it is not the case and requesting a price for any token with >18 decimals from this node will revert.
References
PythNode::process()
:
https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/contracts/oracle/nodes/PythNode.sol#L33-L36
SafeCast::toUint256()
:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/24a641d9c9e0137093592a466c5496315626d98d/contracts/utils/math/SafeCast.sol#L574-L579
Proof of concept
Proof of Concept
In PythNode.test.ts
at the following code here https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/fb92deccd27359ea4f0cf0bc41394c86448c7abb/test/oracle/nodes/PythNode.test.ts#L119 :
To verify the issue is valid without having to make major changes to the mocks and helper files in the codebase, we can just change the PRECISION
value in PythNode.sol
to 6
:
This is because the decimals used for the mock price is 8
. To verify that the call reverts with custom error SafeCastOverflowedIntToUint
, run the test with:
Although this PoC requires changing PythNode.sol
it's exactly the same as if the price had 20 decimals and the PRECISION
was 18 as it is. The intention of this PoC is to visualize the obvious revert from the SafeCast library and so changes required were minimized. The issue itself lays in choosing tokens with large decimals - which would trigger the same error as the test case above.
Last updated