Is the DAO happy with the current limits on the USDREG conversion oracle ?
minAnswer = 0.5 USDREG
(lower limit of the bracket in the smart contract/ also refered to as "the threshold")
maxAnswer = 100 USDREG
(upper limit of the bracket in the smart contract)
Theses values were initialized by RealT as they released the USDREG conversion vault on march 19. (it was discussed with experts over at Chainlink and based on the REG price at the time)
Theses limits can be modified and Michael encouraged the DAO on Telegram to discuss the relevance of the initial values.
This suggestion serves as a means for anyone to follow the debat on:
How should the DAO manage the USDREG conversion Threshold ?
Context :
To put things into context, it's important to understand the impact of this threshold (currently at 0.5) for the USDREG oracle and why it was put in place.
On March 19 2025, a tool appeared to claim your REG. This tool allows you to convert your USDREG (the right to mint REG based on their value).
RealT has implemented a conversion threshold. Currently, it's therefore not possible to convert USDREG below 0.5 per 1 REG.
This threshold is not intended to control the price of REG, but rather to limit high inflation in case of a hack on the oracle.
For instance, if a hacker found a way to manipulate the oracle to return 1 REG = 0.0001 USDREG
, it would then be very easy to create a lot of REG and thus have uncontrolled inflation. This threshold is therefore an essential protection mechanism for the security of REG and its supply. This mechanism could potentially be adjusted over time depending on the liquidity of REG and the level of risk we are willing to take.
We must maintain a balance between a conversion that reflects market reality and a conversion that does not endanger REG and its supply. (do we really have to? Some DAO members have argued against)
Where does this threshold of 0.5 come from? This value, implemented by RealT, is based on Chainlink's recommendations. Chainlink, which is used to managing this type of oracle, recommended 0.5 to protect the REG supply as a minimum (at the time 1 REG was worth between $1.5 and $2). REG markets have especially very low liquidity. If liquidity were sufficient, this threshold would not necessarily be required
How the oracle algorithm works :
You can find the oracle smart-contract here.
Every 24h, the fulfillRegPrice(bytes32,uint256)
function updates the price the oracle (đŽ) returns to the USDREGConversionVault
with an off-chain price
(đ”). This price
(đ”) is calculated from Chainlink's server (more insights on how this price is calculated in the wiki).
Below you can find the conditions (written in english) that acts as the protective measure against hackers:
If the price
(đ”) is within the range [minAnswer
; maxAnswer
] and [regTwapPrice
* (1 - diffFactor
); regTwapPrice
* (1 + diffFactor
)] then update the oracle price (đŽ).
On march 19:
minAnswer = 50000000
(= 0.5 since 8 decimals) => the lower limit of the bracket
maxAnswer = 10000000000
(= 100 since 8 decimals) => the upper limit of the bracket
regTwapPrice
=> The on-chain TWAPOracleREGUSD
calculated price
diffFactor = 500
(= 5% since 10000 = 100%) => probably to check if the off-chain price
(đ”) returned by chainlink's server is not widely off the regTwapPrice
The full fulfillRegPrice(bytes32,uint256 )
function:
function fulfillRegPrice(
bytes32 requestId,
uint256 price
) public recordChainlinkFulfillment(requestId) {
uint256 regTwapPrice = getRegTwapPriceInUsd();
uint256 diffFactorCache = _priceRangeDiffFactor; // cache to save gas
uint256 minAnswerCache = _minAnswer; // cache to save gas
uint256 maxAnswerCache = _maxAnswer; // cache to save gas
// If the price is within the range (minAnswer, maxAnswer) and (regTwapPrice * (1 - diffFactor), regTwapPrice * (1 + diffFactor)) then update the price
if (
price >
((regTwapPrice * (PRICE_RANGE_FACTOR - diffFactorCache)) /
PRICE_RANGE_FACTOR) &&
price <
((regTwapPrice * (PRICE_RANGE_FACTOR + diffFactorCache)) /
PRICE_RANGE_FACTOR) &&
price > minAnswerCache &&
price < maxAnswerCache
) {
// Emit the callback function event
emit RequestRegPriceFulfilled(requestId, price);
_latestAnswer = int256(price);
_latestRound += 1;
_latestTimestamp = block.timestamp;
_answers[_latestRound] = _latestAnswer;
_timestamps[_latestRound] = block.timestamp;
emit AnswerUpdated(int256(price), _latestRound, block.timestamp);
emit NewRound(_latestRound, msg.sender, block.timestamp);
} else {
// Emit the off-chain price out of range event
// Do not revert the transaction to prevent Chainlink automation from stopping
emit OffChainPriceOutOfRange(
price,
regTwapPrice,
diffFactorCache,
minAnswerCache,
maxAnswerCache,
requestId
);
}
}