@ubk-labs/ubk-oracle 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -23,10 +23,13 @@ library UBKOracleConstants {
|
|
|
23
23
|
uint256 public constant ORACLE_MIN_VAULT_RATE_WAD = 0.2e18; // 0.2x (20%)
|
|
24
24
|
uint256 public constant ORACLE_MAX_VAULT_RATE_WAD = 3e18; // 3x (300%)
|
|
25
25
|
|
|
26
|
+
uint256 public constant ORACLE_MAX_VAULT_ASSETS_PER_SHARE = 1e36;
|
|
27
|
+
|
|
26
28
|
// -----------------------------------------------------------------------
|
|
27
29
|
// Oracle Staleness Periods
|
|
28
30
|
// -----------------------------------------------------------------------
|
|
29
31
|
uint256 public constant ORACLE_MIN_STALE_PERIOD = 1 hours;
|
|
32
|
+
uint256 public constant ORACLE_DEFAULT_STALE_PERIOD = 24 hours;
|
|
30
33
|
uint256 public constant ORACLE_MAX_STALE_PERIOD = 48 hours;
|
|
31
34
|
|
|
32
35
|
uint256 public constant ORACLE_DEFAULT_STALE_FALLBACK_MULTIPLIER = 2; //2x stale
|
|
@@ -14,11 +14,11 @@ import "../errors/UBKOracleErrors.sol";
|
|
|
14
14
|
import "../constants/UBKOracleConstants.sol";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* @title
|
|
18
|
-
* @notice This contract is
|
|
17
|
+
* @title UBKOracle
|
|
18
|
+
* @notice This contract is the canonical implementation of the IUBKOracle interface.
|
|
19
19
|
*
|
|
20
20
|
* @dev
|
|
21
|
-
* The
|
|
21
|
+
* The contract computes normalized 1e18 (WAD) prices for all supported assets,
|
|
22
22
|
* combining manual overrides, ERC4626 vault conversions, and Chainlink feeds.
|
|
23
23
|
*
|
|
24
24
|
* === PRICE RESOLUTION ORDER ===
|
|
@@ -26,6 +26,12 @@ import "../constants/UBKOracleConstants.sol";
|
|
|
26
26
|
* 2. ERC4626 vault-derived (convertToAssets * underlying price)
|
|
27
27
|
* 3️. Chainlink feed (normalized to 1e18)
|
|
28
28
|
*
|
|
29
|
+
* === DECIMAL INVARIANTS ===
|
|
30
|
+
* - Only explicitly registered tokens may be priced or converted.
|
|
31
|
+
* - Token decimals are validated once at registration and MUST lie within [6, 18].
|
|
32
|
+
* - Validated decimals are cached immutably and never queried from token contracts at runtime.
|
|
33
|
+
* - All internal price and value computations assume and rely on these enforced bounds.
|
|
34
|
+
* - ERC-4626 vaults are only supported when vault.decimals() == underlying.decimals(), preventing cross-decimal normalization errors in vault pricing.
|
|
29
35
|
* === SAFETY FEATURES ===
|
|
30
36
|
* - Recursion guard (nested ERC4626 depth ≤ 5)
|
|
31
37
|
* - Chainlink stale-period enforcement
|
|
@@ -40,6 +46,7 @@ import "../constants/UBKOracleConstants.sol";
|
|
|
40
46
|
* - UI / Subgraphs can use `isPriceFresh()` and `getPriceAge()` for safety checks.
|
|
41
47
|
*
|
|
42
48
|
*/
|
|
49
|
+
|
|
43
50
|
contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
44
51
|
// -----------------------------------------------------------------------
|
|
45
52
|
// Storage
|
|
@@ -80,6 +87,9 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
80
87
|
/// @notice Mapping to track supported tokens.
|
|
81
88
|
mapping(address => bool) public isSupported;
|
|
82
89
|
|
|
90
|
+
/// @notice Cache that tracks decimals for supported tokens.
|
|
91
|
+
mapping(address => uint8) internal tokenDecimals;
|
|
92
|
+
|
|
83
93
|
// -----------------------------------------------------------------------
|
|
84
94
|
// Constructor & Modifiers
|
|
85
95
|
// -----------------------------------------------------------------------
|
|
@@ -106,6 +116,12 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
106
116
|
_recursionDepth--;
|
|
107
117
|
}
|
|
108
118
|
|
|
119
|
+
/// @notice Does not allow execution of the decorated function if token is unsupported.
|
|
120
|
+
modifier supportedTokenOnly(address token) {
|
|
121
|
+
if (!isSupported[token]) revert TokenNotSupported(token);
|
|
122
|
+
_;
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
// -----------------------------------------------------------------------
|
|
110
126
|
// Admin / Configuration
|
|
111
127
|
// -----------------------------------------------------------------------
|
|
@@ -121,21 +137,11 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
/**
|
|
124
|
-
* @notice
|
|
140
|
+
* @notice External facing admin function that sets the maximum time (in seconds) a Chainlink feed value is valid.
|
|
125
141
|
* @param period The new fallback staleness threshold. Must be 1.5x of stalePeriod of the same token.
|
|
126
|
-
* @dev Must lie within [UBKOracleConstants.ORACLE_MIN_STALE_PERIOD, UBKOracleConstants.ORACLE_MAX_STALE_PERIOD].
|
|
127
142
|
*/
|
|
128
143
|
function setStalePeriod(address token, uint256 period) external onlyOwner {
|
|
129
|
-
|
|
130
|
-
period < UBKOracleConstants.ORACLE_MIN_STALE_PERIOD ||
|
|
131
|
-
period > UBKOracleConstants.ORACLE_MAX_STALE_PERIOD
|
|
132
|
-
) revert InvalidStalePeriod(period);
|
|
133
|
-
stalePeriod[token] = period;
|
|
134
|
-
fallbackStalePeriod[token] =
|
|
135
|
-
UBKOracleConstants.ORACLE_DEFAULT_STALE_FALLBACK_MULTIPLIER *
|
|
136
|
-
period; //Minimum fallback period should be 2x stalePeriod[token].
|
|
137
|
-
emit StalePeriodUpdated(token, stalePeriod[token]);
|
|
138
|
-
emit FallbackStalePeriodUpdated(token, fallbackStalePeriod[token]);
|
|
144
|
+
_setStalePeriod(token, period);
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
/**
|
|
@@ -170,8 +176,11 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
170
176
|
) external onlyOwner {
|
|
171
177
|
if (vault == address(0))
|
|
172
178
|
revert ZeroAddress("UBKOracle::setVaultRateBounds", "vault");
|
|
173
|
-
if (
|
|
174
|
-
|
|
179
|
+
if (
|
|
180
|
+
minRate == 0 ||
|
|
181
|
+
maxRate <= minRate ||
|
|
182
|
+
maxRate > UBKOracleConstants.ORACLE_MAX_VAULT_RATE_WAD
|
|
183
|
+
) revert InvalidVaultBounds(vault, minRate, maxRate);
|
|
175
184
|
|
|
176
185
|
vaultRateBounds[vault] = VaultRateBounds(minRate, maxRate);
|
|
177
186
|
emit VaultRateBoundsSet(vault, minRate, maxRate);
|
|
@@ -190,6 +199,10 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
190
199
|
) external onlyOwner whenNotPaused {
|
|
191
200
|
if (token == address(0))
|
|
192
201
|
revert ZeroAddress("UBKOracle::setManualPrice", "token");
|
|
202
|
+
if (!isSupported[token]) {
|
|
203
|
+
_addSupportedToken(token);
|
|
204
|
+
}
|
|
205
|
+
|
|
193
206
|
if (
|
|
194
207
|
price < UBKOracleConstants.ORACLE_MIN_ABSOLUTE_PRICE_WAD ||
|
|
195
208
|
price > UBKOracleConstants.ORACLE_MAX_ABSOLUTE_PRICE_WAD
|
|
@@ -224,9 +237,9 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
224
237
|
* @notice Disables manual pricing for a token.
|
|
225
238
|
* @param token The token address.
|
|
226
239
|
*/
|
|
227
|
-
function disableManualPrice(
|
|
228
|
-
|
|
229
|
-
|
|
240
|
+
function disableManualPrice(
|
|
241
|
+
address token
|
|
242
|
+
) external onlyOwner supportedTokenOnly(token) {
|
|
230
243
|
isManual[token] = false;
|
|
231
244
|
emit ManualModeEnabled(token, false);
|
|
232
245
|
}
|
|
@@ -265,8 +278,7 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
265
278
|
* @notice Registers an ERC4626 vault and its underlying asset.
|
|
266
279
|
* @param vault ERC4626 vault token.
|
|
267
280
|
* @param underlying Reference underlying asset used for pricing.
|
|
268
|
-
* @dev
|
|
269
|
-
* (e.g., sUSDe → USDC pegging for depeg protection).
|
|
281
|
+
* @dev Stricly enforces == underlying for flexibility
|
|
270
282
|
*/
|
|
271
283
|
function setERC4626Vault(
|
|
272
284
|
address vault,
|
|
@@ -299,8 +311,6 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
299
311
|
function fetchAndUpdatePrice(
|
|
300
312
|
address token
|
|
301
313
|
) external whenNotPaused returns (uint256) {
|
|
302
|
-
if (token == address(0))
|
|
303
|
-
revert ZeroAddress("UBKOracle::fetchAndUpdatePrice", "token");
|
|
304
314
|
return _fetchAndUpdatePrice(token);
|
|
305
315
|
}
|
|
306
316
|
|
|
@@ -373,17 +383,28 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
373
383
|
// -----------------------------------------------------------------------
|
|
374
384
|
|
|
375
385
|
/**
|
|
376
|
-
* @notice Converts a token amount into USD (18 decimals)
|
|
377
|
-
* @
|
|
378
|
-
*
|
|
379
|
-
*
|
|
386
|
+
* @notice Converts a supported token amount into USD (18 decimals).
|
|
387
|
+
* @dev
|
|
388
|
+
* Requirements:
|
|
389
|
+
* - `token` MUST be registered as supported by the oracle.
|
|
390
|
+
* - Token decimals are cached at registration and guaranteed to be within [6,18].
|
|
391
|
+
* - Reverts if the token is not supported or if the cached price is stale or unavailable.
|
|
392
|
+
*
|
|
393
|
+
* Behavior:
|
|
394
|
+
* - Returns 0 if `amount == 0` without reading oracle price.
|
|
395
|
+
* - Uses cached decimals and cached price for deterministic gas usage.
|
|
396
|
+
*
|
|
397
|
+
* @param token Supported token address.
|
|
398
|
+
* @param amount Raw token amount in native decimals.
|
|
399
|
+
* @return usdValue USD value with 18 decimals of precision.
|
|
380
400
|
*/
|
|
401
|
+
|
|
381
402
|
function toUSD(
|
|
382
403
|
address token,
|
|
383
404
|
uint256 amount
|
|
384
405
|
) external view returns (uint256 usdValue) {
|
|
385
406
|
if (amount == 0) return 0;
|
|
386
|
-
uint8 decimals =
|
|
407
|
+
uint8 decimals = tokenDecimals[token];
|
|
387
408
|
uint256 normalized = (amount * UBKOracleConstants.WAD) /
|
|
388
409
|
(10 ** decimals);
|
|
389
410
|
uint256 price = _getPrice(token); // 18 decimals
|
|
@@ -391,17 +412,28 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
391
412
|
}
|
|
392
413
|
|
|
393
414
|
/**
|
|
394
|
-
* @notice Converts a USD amount (18 decimals) into token
|
|
395
|
-
* @
|
|
396
|
-
*
|
|
397
|
-
*
|
|
415
|
+
* @notice Converts a USD amount (18 decimals) into units of a supported token.
|
|
416
|
+
* @dev
|
|
417
|
+
* Requirements:
|
|
418
|
+
* - `token` MUST be registered as supported by the oracle.
|
|
419
|
+
* - Token decimals are cached at registration and guaranteed to be within [6,18].
|
|
420
|
+
* - Reverts if the token is not supported or if the cached price is stale or unavailable.
|
|
421
|
+
*
|
|
422
|
+
* Behavior:
|
|
423
|
+
* - Returns 0 if `usdAmount == 0` without reading oracle price.
|
|
424
|
+
* - Uses cached decimals and cached price for deterministic gas usage.
|
|
425
|
+
*
|
|
426
|
+
* @param token Supported token address.
|
|
427
|
+
* @param usdAmount USD value with 18 decimals of precision.
|
|
428
|
+
* @return tokenAmount Equivalent amount in token native decimals.
|
|
398
429
|
*/
|
|
430
|
+
|
|
399
431
|
function fromUSD(
|
|
400
432
|
address token,
|
|
401
433
|
uint256 usdAmount
|
|
402
434
|
) external view returns (uint256 tokenAmount) {
|
|
403
435
|
if (usdAmount == 0) return 0;
|
|
404
|
-
uint8 decimals =
|
|
436
|
+
uint8 decimals = tokenDecimals[token];
|
|
405
437
|
uint256 price = _getPrice(token); // 18 decimals
|
|
406
438
|
uint256 normalized = (usdAmount * UBKOracleConstants.WAD) / price;
|
|
407
439
|
tokenAmount = (normalized * (10 ** decimals)) / UBKOracleConstants.WAD;
|
|
@@ -412,14 +444,35 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
412
444
|
// -----------------------------------------------------------------------
|
|
413
445
|
|
|
414
446
|
/**
|
|
415
|
-
* @notice Returns the cached price for a token
|
|
416
|
-
*
|
|
447
|
+
* @notice Returns the cached USD price for a token.
|
|
448
|
+
*
|
|
449
|
+
* @dev
|
|
450
|
+
* This function is the canonical read path for all pricing operations
|
|
451
|
+
* (including `toUSD` and `fromUSD`). It intentionally performs **no explicit
|
|
452
|
+
* supported-token check** in order to minimize gas usage on hot, view-only paths.
|
|
453
|
+
*
|
|
454
|
+
* Reverts in the following cases:
|
|
455
|
+
*
|
|
456
|
+
* 1. `NoFallbackPrice(token)`
|
|
457
|
+
* - The token has **never had a successfully resolved and cached price**, OR
|
|
458
|
+
* - The token is **unsupported** and therefore has no initialized pricing state.
|
|
459
|
+
*
|
|
460
|
+
* 2. `StalePrice(token, lastUpdated, now)`
|
|
461
|
+
* - A cached price exists, but its age exceeds `stalePeriod[token]`.
|
|
462
|
+
*
|
|
463
|
+
* Supported tokens are guaranteed to have:
|
|
464
|
+
* - non-zero addresses,
|
|
465
|
+
* - validated and cached decimals within [6, 18],
|
|
466
|
+
* - pricing state initialized only via explicit configuration paths
|
|
467
|
+
* (e.g. Chainlink feeds, ERC4626 vaults, or manual pricing).
|
|
468
|
+
*
|
|
469
|
+
* As a result, callers of `toUSD` and `fromUSD` can safely rely on this function
|
|
470
|
+
* for correctness while avoiding redundant SLOADs or branching.
|
|
471
|
+
*
|
|
417
472
|
* @param token Asset token address.
|
|
418
|
-
* @return price Cached price in 1e18 precision.
|
|
473
|
+
* @return price Cached token price in 1e18 precision.
|
|
419
474
|
*/
|
|
420
|
-
function _getPrice(address token) internal view returns (uint256) {
|
|
421
|
-
if (token == address(0))
|
|
422
|
-
revert ZeroAddress("UBKOracle::getPrice", "token");
|
|
475
|
+
function _getPrice(address token) internal view returns (uint256 price) {
|
|
423
476
|
LastValidPrice memory lv = lastValidPrice[token];
|
|
424
477
|
if (lv.price == 0) revert NoFallbackPrice(token);
|
|
425
478
|
if (!_isPriceFresh(token))
|
|
@@ -446,17 +499,20 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
446
499
|
* @dev Derives price via convertToAssets() * underlying price.
|
|
447
500
|
* Ensures vault rate lies within acceptable bounds.
|
|
448
501
|
*/
|
|
449
|
-
function
|
|
502
|
+
function _resolveVaultPrice(
|
|
450
503
|
address vault,
|
|
451
504
|
address underlying
|
|
452
505
|
) internal checkRecursion returns (uint256 price) {
|
|
453
|
-
uint8 shareDecimals =
|
|
454
|
-
uint8 underlyingDecimals =
|
|
506
|
+
uint8 shareDecimals = tokenDecimals[vault];
|
|
507
|
+
uint8 underlyingDecimals = tokenDecimals[underlying];
|
|
455
508
|
|
|
456
509
|
uint256 oneShare = 10 ** shareDecimals;
|
|
457
510
|
uint256 assetsPerShare = IERC4626(vault).convertToAssets(oneShare);
|
|
458
|
-
if (
|
|
459
|
-
|
|
511
|
+
if (
|
|
512
|
+
assetsPerShare == 0 ||
|
|
513
|
+
assetsPerShare >
|
|
514
|
+
UBKOracleConstants.ORACLE_MAX_VAULT_ASSETS_PER_SHARE
|
|
515
|
+
) revert InvalidVaultExchangeRate(vault, assetsPerShare);
|
|
460
516
|
|
|
461
517
|
uint256 scaledAssets = (assetsPerShare * UBKOracleConstants.WAD) /
|
|
462
518
|
(10 ** underlyingDecimals);
|
|
@@ -541,11 +597,14 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
541
597
|
* @return price Resolved fair price in 1e18 precision.
|
|
542
598
|
* @dev May trigger state updates if underlying vaults are resolved.
|
|
543
599
|
*/
|
|
544
|
-
function _resolvePrice(
|
|
600
|
+
function _resolvePrice(
|
|
601
|
+
address token
|
|
602
|
+
) internal supportedTokenOnly(token) returns (uint256 price) {
|
|
545
603
|
if (isManual[token]) return manualPrices[token];
|
|
546
604
|
|
|
547
605
|
address underlying = erc4626Underlying[token];
|
|
548
|
-
if (underlying != address(0))
|
|
606
|
+
if (underlying != address(0))
|
|
607
|
+
return _resolveVaultPrice(token, underlying);
|
|
549
608
|
|
|
550
609
|
address feed = chainlinkFeeds[token];
|
|
551
610
|
if (feed == address(0)) revert NoPriceFeed(token);
|
|
@@ -580,7 +639,7 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
580
639
|
if (
|
|
581
640
|
price < UBKOracleConstants.ORACLE_MIN_ABSOLUTE_PRICE_WAD ||
|
|
582
641
|
price > UBKOracleConstants.ORACLE_MAX_ABSOLUTE_PRICE_WAD
|
|
583
|
-
) revert InvalidOraclePrice(token,
|
|
642
|
+
) revert InvalidOraclePrice(token, price);
|
|
584
643
|
|
|
585
644
|
lastValidPrice[token] = LastValidPrice(price, block.timestamp);
|
|
586
645
|
emit LastValidPriceUpdated(token, price, block.timestamp);
|
|
@@ -598,9 +657,18 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
598
657
|
* Emits a {TokenSupportAdded} event upon successful addition.
|
|
599
658
|
*/
|
|
600
659
|
function _addSupportedToken(address token) internal {
|
|
660
|
+
if (token == address(0)) {
|
|
661
|
+
revert ZeroAddress("UBKOracle::_addSupportedToken", "token");
|
|
662
|
+
}
|
|
663
|
+
|
|
601
664
|
if (!isSupported[token]) {
|
|
602
665
|
supportedTokens.push(token);
|
|
603
666
|
isSupported[token] = true;
|
|
667
|
+
tokenDecimals[token] = _validateTokenDecimals(token);
|
|
668
|
+
_setStalePeriod(
|
|
669
|
+
token,
|
|
670
|
+
UBKOracleConstants.ORACLE_DEFAULT_STALE_PERIOD
|
|
671
|
+
);
|
|
604
672
|
emit TokenSupportAdded(token);
|
|
605
673
|
}
|
|
606
674
|
}
|
|
@@ -652,4 +720,22 @@ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
|
|
|
652
720
|
);
|
|
653
721
|
}
|
|
654
722
|
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* @notice Sets the maximum time (in seconds) a Chainlink feed value is valid.
|
|
726
|
+
* @param period The new fallback staleness threshold. Must be 1.5x of stalePeriod of the same token.
|
|
727
|
+
* @dev Must lie within [UBKOracleConstants.ORACLE_MIN_STALE_PERIOD, UBKOracleConstants.ORACLE_MAX_STALE_PERIOD].
|
|
728
|
+
*/
|
|
729
|
+
function _setStalePeriod(address token, uint256 period) internal {
|
|
730
|
+
if (
|
|
731
|
+
period < UBKOracleConstants.ORACLE_MIN_STALE_PERIOD ||
|
|
732
|
+
period > UBKOracleConstants.ORACLE_MAX_STALE_PERIOD
|
|
733
|
+
) revert InvalidStalePeriod(period);
|
|
734
|
+
stalePeriod[token] = period;
|
|
735
|
+
fallbackStalePeriod[token] =
|
|
736
|
+
UBKOracleConstants.ORACLE_DEFAULT_STALE_FALLBACK_MULTIPLIER *
|
|
737
|
+
period; //Minimum fallback period should be 2x stalePeriod[token].
|
|
738
|
+
emit StalePeriodUpdated(token, stalePeriod[token]);
|
|
739
|
+
emit FallbackStalePeriodUpdated(token, fallbackStalePeriod[token]);
|
|
740
|
+
}
|
|
655
741
|
}
|
|
@@ -4,19 +4,24 @@ pragma solidity ^0.8.20;
|
|
|
4
4
|
import "@ubk-labs/ubk-commons/contracts/errors/UBKErrors.sol";
|
|
5
5
|
|
|
6
6
|
// ───────────── Errors ─────────────
|
|
7
|
+
error ERC4626DecimalsMismatch(
|
|
8
|
+
string functionName,
|
|
9
|
+
address vault,
|
|
10
|
+
address underlying
|
|
11
|
+
);
|
|
12
|
+
error InvalidERC4626Vault(address vault);
|
|
13
|
+
error InvalidFeedContract(address feed);
|
|
14
|
+
error InvalidFeedDecimals(address feed, uint8 decimals);
|
|
7
15
|
error InvalidManualPrice(address token, uint256 price);
|
|
16
|
+
error InvalidOraclePrice(address token, uint256 price);
|
|
8
17
|
error InvalidStalePeriod(uint256 period);
|
|
9
18
|
error InvalidVaultBounds(address vault, uint256 minRate, uint256 maxRate);
|
|
10
|
-
error InvalidFeedContract(address feed);
|
|
11
|
-
error InvalidFeedDecimals(address feed, uint8 decimals);
|
|
12
|
-
error InvalidERC4626Vault(address vault);
|
|
13
19
|
error InvalidVaultExchangeRate(address vault, uint256 rate);
|
|
14
|
-
error
|
|
20
|
+
error NoFallbackPrice(address token);
|
|
15
21
|
error NoPriceFeed(address token);
|
|
16
|
-
error
|
|
22
|
+
error OraclePaused(address oracle, uint256 timestamp);
|
|
23
|
+
error RecursiveResolution(address token);
|
|
17
24
|
error StaleFallback(address token);
|
|
18
|
-
error
|
|
25
|
+
error StalePrice(address token, uint256 updatedAt, uint256 currentTime);
|
|
19
26
|
error SuspiciousVaultRate(address vault, uint256 rate);
|
|
20
|
-
error
|
|
21
|
-
error OraclePaused(address oracle, uint256 timestamp);
|
|
22
|
-
error ERC4626DecimalsMismatch(string functionName, address vault, address underlying);
|
|
27
|
+
error TokenNotSupported(address token);
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ubk-labs/ubk-oracle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Oracle supporting ERC-20 and ERC-4626 assets for use in decentralized financial applications.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npx hardhat compile",
|
|
7
7
|
"test": "npx hardhat test",
|
|
8
8
|
"coverage": "hardhat coverage",
|
|
9
9
|
"lint": "prettier --check .",
|
|
10
|
-
"format": "prettier --write ."
|
|
10
|
+
"format": "prettier --write .",
|
|
11
|
+
"deploy:mainnet": "npx hardhat run scripts/deploy.js --network mainnet"
|
|
11
12
|
},
|
|
12
13
|
"keywords": [
|
|
13
14
|
"DeFi",
|