Just after the change was made, we found an edge case where transfers are reverting if a price has not been updated after a user exchanges into a Synth. The issue relates to how fee reclamation is calculated.
This SIP will fix the issue by using low level calls to the Chainlink aggregator's
getRoundData functions in order to avoid any reverts in case the requested round ID does not exist.
This will act as a
try/catch method which will allow the
ExchangeRates contract to only update a rate if the previous call to the aggregator was successful.
In the previous version of Chainlink's aggregator interface, the function
getRoundData(uint roundId) was returning 0 in case
roundId was not found.
This was helpful for the
ExchangeRates contract to know if a new round ID existed or not during the calculation of fee reclamation, by calling
getRoundData(roundId + 1). If the result was returning 0, the current round ID was kept for the next steps.
However, this logic was changed in the latest aggregator interface. Calling
getRoundData(roundId) is now reverting if
roundId cannot be found, which makes the current logic obsolete.
This SIP will implement low-level calls to Chainlink aggregator's
getLatestRoundData() functions in order to suppress any reverts.
bytes memory payload = abi.encodeWithSignature("getRoundData(uint80)", roundId); (bool success, bytes memory returnData) = address(aggregator).staticcall(payload);
As shown above,
staticcall is used here to avoid
getRoundData() from reverting, returning
success is true,
ExchangeRates will then update the rates with
success is false, we do nothing.
A production test will need to be added with the following scenario:
- Exchange a synth from sUSD to sETH
- Wait the required amount of time for a transaction to be allowed to settle (
- Settle sETH
This scenario will only pass if the patch described in this SIP is implemented. It will fail otherwise.