Platform: Code4rena
Start Date: 09/12/2022
Pot Size: $90,500 USDC
Total HM: 35
Participants: 84
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 12
Id: 192
League: ETH
Rank: 65/84
Findings: 2
Award: $25.45
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: yjrwkk
Also found by: 0x4non, 0xDecorativePineapple, 0xdeadbeef0x, Avci, Critical, Deivitto, Dinesh11G, Englave, Tointer, ak1, chaduke, izhelyazkov, pwnforce, rbserver, rvierdiiev, unforgiven
13.7578 USDC - $13.76
https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/StableVault.sol#L67 https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/utils/TradingLibrary.sol#L115
It has been identified that the Tigris project incorrectly handles the decimals of ERC20 tokens. Specifically:
In the StableVault.sol
contract, the calculation that scales the value of the deposited amount assumes that the _token
supplied by the user has less than 18 decimals: _amount*(10**(18-IERC20Mintable(_token).decimals()))
. This is not always true, as ERC20 tokens may have more than 18 decimals, resulting in a contract call that will revert.
There are some places in the codebase that ERC20 tokens are assumed to have 18 decimals. For example, in the TradingLibrary.sol:verifyPrice()
function (https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/utils/TradingLibrary.sol#L115), the price provided in the PriceData
struct is assumed to have 18 decimals. The contract then scales the price retrieved from a Chainlink feed to 18 decimals, assuming that the provided price(in the PriceData
struct ) has 18 decimals as well. This verifyPrice
function is used to verify that the price provided in the PriceData
struct is close to the one fetched from Chainlink. However, if the decimals of the ERC20 token are different than 18, this could result in incorrect calculations and even prevent trades from being initiated/closed or margin from being removed.
To handle the fact that ERC20 token decimals may be different than 18, a solution can be implemented to scale the token decimals between different ERC20 tokens. An example of this can be found in Chainlink's scalePrice
function (https://docs.chain.link/docs/get-the-latest-price/#getting-a-different-price-denomination).
#0 - c4-judge
2022-12-20T15:43:23Z
GalloDaSballo marked the issue as duplicate of #533
#1 - c4-judge
2023-01-22T17:45:09Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: rbserver
Also found by: 0x52, 0xDecorativePineapple, 0xdeadbeef0x, 8olidity, Jeiwan, Rolezn, __141345__, bin2chen, eierina, fs0c, gzeon, joestakey, koxuan, kwhuo68, ladboy233, rvierdiiev, yixxas
11.6941 USDC - $11.69
The latestAnswer()
function for ERC20 is deprecated according to Chainlink's documentation. This can lead to the following issues:
_chainlinkEnabled
is set and Chainlink no longer supports deprecated APIs, the contract may face a Denial of Service (DoS), as prices cannot be obtained and new trades cannot be initiated or executed.latestAnswer
function only returns the value of the latest price, whereas latestRoundData
returns additional information that can be used to validate whether a price is stale.The verifyPrice
function uses the deprecated latestAnswer()
API:
function verifyPrice( ... if (_chainlinkEnabled && _chainlinkFeed != address(0)) { int256 assetChainlinkPriceInt = IPrice(_chainlinkFeed).latestAnswer(); if (assetChainlinkPriceInt != 0) { .. }
Manual Code Review
It's recommended to use the latest latestRoundData
function and validate the oracle response for freshness and round completion in addition to nonzero price:
(uint80 roundID, int256 price, , uint256 timeStamp, uint80 answeredInRound) = IPrice(_chainlinkFeed).latestRoundData(); require(answeredInRound >= roundID, "..."); require(timeStamp != 0, "..."); require(price != 0, "...");
For more information, please refer to the Chainlink documentation on latestAnswer.
#0 - c4-judge
2022-12-20T16:35:02Z
GalloDaSballo marked the issue as duplicate of #655
#1 - c4-judge
2023-01-22T17:31:05Z
GalloDaSballo marked the issue as satisfactory