@ubk-labs/ubk-oracle 0.1.8 → 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
@@ -7,17 +7,18 @@ import "@openzeppelin/contracts/interfaces/IERC4626.sol";
7
7
  import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
8
8
 
9
9
  import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
10
+ import "@ubk-labs/ubk-commons/contracts/abstract/UBKDecimalsBounded.sol";
10
11
 
11
12
  import "../../interfaces/IUBKOracle.sol";
12
13
  import "../errors/UBKOracleErrors.sol";
13
14
  import "../constants/UBKOracleConstants.sol";
14
15
 
15
16
  /**
16
- * @title Oracle
17
- * @notice This contract is an implementation of the IUBKOracle interface.
17
+ * @title UBKOracle
18
+ * @notice This contract is the canonical implementation of the IUBKOracle interface.
18
19
  *
19
20
  * @dev
20
- * The oracle computes normalized 1e18 prices for all supported assets,
21
+ * The contract computes normalized 1e18 (WAD) prices for all supported assets,
21
22
  * combining manual overrides, ERC4626 vault conversions, and Chainlink feeds.
22
23
  *
23
24
  * === PRICE RESOLUTION ORDER ===
@@ -25,6 +26,12 @@ import "../constants/UBKOracleConstants.sol";
25
26
  * 2. ERC4626 vault-derived (convertToAssets * underlying price)
26
27
  * 3️. Chainlink feed (normalized to 1e18)
27
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.
28
35
  * === SAFETY FEATURES ===
29
36
  * - Recursion guard (nested ERC4626 depth ≤ 5)
30
37
  * - Chainlink stale-period enforcement
@@ -39,7 +46,8 @@ import "../constants/UBKOracleConstants.sol";
39
46
  * - UI / Subgraphs can use `isPriceFresh()` and `getPriceAge()` for safety checks.
40
47
  *
41
48
  */
42
- contract UBKOracle is IUBKOracle, Ownable {
49
+
50
+ contract UBKOracle is IUBKOracle, UBKDecimalsBounded, Ownable {
43
51
  // -----------------------------------------------------------------------
44
52
  // Storage
45
53
  // -----------------------------------------------------------------------
@@ -79,6 +87,9 @@ contract UBKOracle is IUBKOracle, Ownable {
79
87
  /// @notice Mapping to track supported tokens.
80
88
  mapping(address => bool) public isSupported;
81
89
 
90
+ /// @notice Cache that tracks decimals for supported tokens.
91
+ mapping(address => uint8) internal tokenDecimals;
92
+
82
93
  // -----------------------------------------------------------------------
83
94
  // Constructor & Modifiers
84
95
  // -----------------------------------------------------------------------
@@ -87,10 +98,7 @@ contract UBKOracle is IUBKOracle, Ownable {
87
98
  * @notice Deploys the Oracle contract.
88
99
  * @param _owner The address to assign as the owner (governance or deployer).
89
100
  */
90
- constructor(address _owner) Ownable(_owner) {
91
- if (_owner == address(0))
92
- revert ZeroAddress("UBKOracle::constructor", "owner");
93
- }
101
+ constructor(address _owner) Ownable(_owner) {}
94
102
 
95
103
  /// @notice Ensures oracle is not paused.
96
104
  modifier whenNotPaused() {
@@ -108,6 +116,12 @@ contract UBKOracle is IUBKOracle, Ownable {
108
116
  _recursionDepth--;
109
117
  }
110
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
+
111
125
  // -----------------------------------------------------------------------
112
126
  // Admin / Configuration
113
127
  // -----------------------------------------------------------------------
@@ -123,21 +137,11 @@ contract UBKOracle is IUBKOracle, Ownable {
123
137
  }
124
138
 
125
139
  /**
126
- * @notice Sets the maximum time (in seconds) a Chainlink feed value is valid.
140
+ * @notice External facing admin function that sets the maximum time (in seconds) a Chainlink feed value is valid.
127
141
  * @param period The new fallback staleness threshold. Must be 1.5x of stalePeriod of the same token.
128
- * @dev Must lie within [UBKOracleConstants.ORACLE_MIN_STALE_PERIOD, UBKOracleConstants.ORACLE_MAX_STALE_PERIOD].
129
142
  */
130
143
  function setStalePeriod(address token, uint256 period) external onlyOwner {
131
- if (
132
- period < UBKOracleConstants.ORACLE_MIN_STALE_PERIOD ||
133
- period > UBKOracleConstants.ORACLE_MAX_STALE_PERIOD
134
- ) revert InvalidStalePeriod(period);
135
- stalePeriod[token] = period;
136
- fallbackStalePeriod[token] =
137
- UBKOracleConstants.ORACLE_DEFAULT_STALE_FALLBACK_MULTIPLIER *
138
- period; //Minimum fallback period should be 2x stalePeriod[token].
139
- emit StalePeriodUpdated(token, stalePeriod[token]);
140
- emit FallbackStalePeriodUpdated(token, fallbackStalePeriod[token]);
144
+ _setStalePeriod(token, period);
141
145
  }
142
146
 
143
147
  /**
@@ -172,8 +176,11 @@ contract UBKOracle is IUBKOracle, Ownable {
172
176
  ) external onlyOwner {
173
177
  if (vault == address(0))
174
178
  revert ZeroAddress("UBKOracle::setVaultRateBounds", "vault");
175
- if (minRate == 0 || maxRate <= minRate || maxRate > 100e18)
176
- revert InvalidVaultBounds(vault, minRate, maxRate);
179
+ if (
180
+ minRate == 0 ||
181
+ maxRate <= minRate ||
182
+ maxRate > UBKOracleConstants.ORACLE_MAX_VAULT_RATE_WAD
183
+ ) revert InvalidVaultBounds(vault, minRate, maxRate);
177
184
 
178
185
  vaultRateBounds[vault] = VaultRateBounds(minRate, maxRate);
179
186
  emit VaultRateBoundsSet(vault, minRate, maxRate);
@@ -192,6 +199,10 @@ contract UBKOracle is IUBKOracle, Ownable {
192
199
  ) external onlyOwner whenNotPaused {
193
200
  if (token == address(0))
194
201
  revert ZeroAddress("UBKOracle::setManualPrice", "token");
202
+ if (!isSupported[token]) {
203
+ _addSupportedToken(token);
204
+ }
205
+
195
206
  if (
196
207
  price < UBKOracleConstants.ORACLE_MIN_ABSOLUTE_PRICE_WAD ||
197
208
  price > UBKOracleConstants.ORACLE_MAX_ABSOLUTE_PRICE_WAD
@@ -226,9 +237,9 @@ contract UBKOracle is IUBKOracle, Ownable {
226
237
  * @notice Disables manual pricing for a token.
227
238
  * @param token The token address.
228
239
  */
229
- function disableManualPrice(address token) external onlyOwner {
230
- if (token == address(0))
231
- revert ZeroAddress("UBKOracle::disableManualPrice", "token");
240
+ function disableManualPrice(
241
+ address token
242
+ ) external onlyOwner supportedTokenOnly(token) {
232
243
  isManual[token] = false;
233
244
  emit ManualModeEnabled(token, false);
234
245
  }
@@ -240,9 +251,7 @@ contract UBKOracle is IUBKOracle, Ownable {
240
251
  * @dev Ensures decimals ≤ 18 and feed returns a nonzero updatedAt value.
241
252
  */
242
253
  function setChainlinkFeed(address token, address feed) external onlyOwner {
243
- if (token == address(0) || feed == address(0))
244
- revert ZeroAddress("UBKOracle::setChainlinkFeed", "input");
245
- if (feed.code.length == 0) revert InvalidFeedContract(feed);
254
+ _validateChainlinkFeed(token, feed);
246
255
 
247
256
  AggregatorV3Interface agg = AggregatorV3Interface(feed);
248
257
  uint8 decimals = agg.decimals();
@@ -269,18 +278,13 @@ contract UBKOracle is IUBKOracle, Ownable {
269
278
  * @notice Registers an ERC4626 vault and its underlying asset.
270
279
  * @param vault ERC4626 vault token.
271
280
  * @param underlying Reference underlying asset used for pricing.
272
- * @dev Does not enforce .asset() == underlying for flexibility
273
- * (e.g., sUSDe → USDC pegging for depeg protection).
281
+ * @dev Stricly enforces == underlying for flexibility
274
282
  */
275
283
  function setERC4626Vault(
276
284
  address vault,
277
285
  address underlying
278
286
  ) external onlyOwner {
279
- if (vault == address(0) || underlying == address(0))
280
- revert ZeroAddress("UBKOracle::setERC4626Vault", "input");
281
- try IERC4626(vault).asset() returns (address) {} catch {
282
- revert InvalidERC4626Vault(vault);
283
- }
287
+ _validateERC4626Vault(vault, underlying);
284
288
  erc4626Underlying[vault] = underlying;
285
289
  _addSupportedToken(vault);
286
290
  emit ERC4626Registered(vault, underlying);
@@ -307,8 +311,6 @@ contract UBKOracle is IUBKOracle, Ownable {
307
311
  function fetchAndUpdatePrice(
308
312
  address token
309
313
  ) external whenNotPaused returns (uint256) {
310
- if (token == address(0))
311
- revert ZeroAddress("UBKOracle::fetchAndUpdatePrice", "token");
312
314
  return _fetchAndUpdatePrice(token);
313
315
  }
314
316
 
@@ -381,17 +383,28 @@ contract UBKOracle is IUBKOracle, Ownable {
381
383
  // -----------------------------------------------------------------------
382
384
 
383
385
  /**
384
- * @notice Converts a token amount into USD (18 decimals)
385
- * @param token Token address
386
- * @param amount Raw token amount (native decimals)
387
- * @return usdValue USD value (18 decimals)
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.
388
400
  */
401
+
389
402
  function toUSD(
390
403
  address token,
391
404
  uint256 amount
392
405
  ) external view returns (uint256 usdValue) {
393
406
  if (amount == 0) return 0;
394
- uint8 decimals = IERC20Metadata(token).decimals();
407
+ uint8 decimals = tokenDecimals[token];
395
408
  uint256 normalized = (amount * UBKOracleConstants.WAD) /
396
409
  (10 ** decimals);
397
410
  uint256 price = _getPrice(token); // 18 decimals
@@ -399,17 +412,28 @@ contract UBKOracle is IUBKOracle, Ownable {
399
412
  }
400
413
 
401
414
  /**
402
- * @notice Converts a USD amount (18 decimals) into token units
403
- * @param token Token address
404
- * @param usdAmount USD value (18 decimals)
405
- * @return tokenAmount Equivalent in token units
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.
406
429
  */
430
+
407
431
  function fromUSD(
408
432
  address token,
409
433
  uint256 usdAmount
410
434
  ) external view returns (uint256 tokenAmount) {
411
435
  if (usdAmount == 0) return 0;
412
- uint8 decimals = IERC20Metadata(token).decimals();
436
+ uint8 decimals = tokenDecimals[token];
413
437
  uint256 price = _getPrice(token); // 18 decimals
414
438
  uint256 normalized = (usdAmount * UBKOracleConstants.WAD) / price;
415
439
  tokenAmount = (normalized * (10 ** decimals)) / UBKOracleConstants.WAD;
@@ -420,14 +444,35 @@ contract UBKOracle is IUBKOracle, Ownable {
420
444
  // -----------------------------------------------------------------------
421
445
 
422
446
  /**
423
- * @notice Returns the cached price for a token (1e18 precision).
424
- * @dev Reverts if no valid price or if staleness > stalePeriod.
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
+ *
425
472
  * @param token Asset token address.
426
- * @return price Cached price in 1e18 precision.
473
+ * @return price Cached token price in 1e18 precision.
427
474
  */
428
- function _getPrice(address token) internal view returns (uint256) {
429
- if (token == address(0))
430
- revert ZeroAddress("UBKOracle::getPrice", "token");
475
+ function _getPrice(address token) internal view returns (uint256 price) {
431
476
  LastValidPrice memory lv = lastValidPrice[token];
432
477
  if (lv.price == 0) revert NoFallbackPrice(token);
433
478
  if (!_isPriceFresh(token))
@@ -454,17 +499,20 @@ contract UBKOracle is IUBKOracle, Ownable {
454
499
  * @dev Derives price via convertToAssets() * underlying price.
455
500
  * Ensures vault rate lies within acceptable bounds.
456
501
  */
457
- function _getVaultPrice(
502
+ function _resolveVaultPrice(
458
503
  address vault,
459
504
  address underlying
460
505
  ) internal checkRecursion returns (uint256 price) {
461
- uint8 shareDecimals = IERC20Metadata(vault).decimals();
462
- uint8 underlyingDecimals = IERC20Metadata(underlying).decimals();
506
+ uint8 shareDecimals = tokenDecimals[vault];
507
+ uint8 underlyingDecimals = tokenDecimals[underlying];
463
508
 
464
509
  uint256 oneShare = 10 ** shareDecimals;
465
510
  uint256 assetsPerShare = IERC4626(vault).convertToAssets(oneShare);
466
- if (assetsPerShare == 0 || assetsPerShare > 1e36)
467
- revert InvalidVaultExchangeRate(vault, assetsPerShare);
511
+ if (
512
+ assetsPerShare == 0 ||
513
+ assetsPerShare >
514
+ UBKOracleConstants.ORACLE_MAX_VAULT_ASSETS_PER_SHARE
515
+ ) revert InvalidVaultExchangeRate(vault, assetsPerShare);
468
516
 
469
517
  uint256 scaledAssets = (assetsPerShare * UBKOracleConstants.WAD) /
470
518
  (10 ** underlyingDecimals);
@@ -549,11 +597,14 @@ contract UBKOracle is IUBKOracle, Ownable {
549
597
  * @return price Resolved fair price in 1e18 precision.
550
598
  * @dev May trigger state updates if underlying vaults are resolved.
551
599
  */
552
- function _resolvePrice(address token) internal returns (uint256 price) {
600
+ function _resolvePrice(
601
+ address token
602
+ ) internal supportedTokenOnly(token) returns (uint256 price) {
553
603
  if (isManual[token]) return manualPrices[token];
554
604
 
555
605
  address underlying = erc4626Underlying[token];
556
- if (underlying != address(0)) return _getVaultPrice(token, underlying);
606
+ if (underlying != address(0))
607
+ return _resolveVaultPrice(token, underlying);
557
608
 
558
609
  address feed = chainlinkFeeds[token];
559
610
  if (feed == address(0)) revert NoPriceFeed(token);
@@ -588,7 +639,7 @@ contract UBKOracle is IUBKOracle, Ownable {
588
639
  if (
589
640
  price < UBKOracleConstants.ORACLE_MIN_ABSOLUTE_PRICE_WAD ||
590
641
  price > UBKOracleConstants.ORACLE_MAX_ABSOLUTE_PRICE_WAD
591
- ) revert InvalidOraclePrice(token, address(0));
642
+ ) revert InvalidOraclePrice(token, price);
592
643
 
593
644
  lastValidPrice[token] = LastValidPrice(price, block.timestamp);
594
645
  emit LastValidPriceUpdated(token, price, block.timestamp);
@@ -606,10 +657,85 @@ contract UBKOracle is IUBKOracle, Ownable {
606
657
  * Emits a {TokenSupportAdded} event upon successful addition.
607
658
  */
608
659
  function _addSupportedToken(address token) internal {
660
+ if (token == address(0)) {
661
+ revert ZeroAddress("UBKOracle::_addSupportedToken", "token");
662
+ }
663
+
609
664
  if (!isSupported[token]) {
610
665
  supportedTokens.push(token);
611
666
  isSupported[token] = true;
667
+ tokenDecimals[token] = _validateTokenDecimals(token);
668
+ _setStalePeriod(
669
+ token,
670
+ UBKOracleConstants.ORACLE_DEFAULT_STALE_PERIOD
671
+ );
612
672
  emit TokenSupportAdded(token);
613
673
  }
614
674
  }
675
+
676
+ /**
677
+ * @notice Validates assets and their associated Chainlink feeds before mutating system state.
678
+ * @param token Asset token address.
679
+ * @param feed Chainlink AggregatorV3 feed address.
680
+ * @dev Ensures decimals ≤ 18 and feed returns a nonzero updatedAt value.
681
+ */
682
+ function _validateChainlinkFeed(address token, address feed) internal view {
683
+ if (token == address(0))
684
+ revert ZeroAddress("UBKOracle::setChainlinkFeed", "token");
685
+ if (feed == address(0))
686
+ revert ZeroAddress("UBKOracle::setChainlinkFeed", "feed");
687
+ if (feed.code.length == 0) revert InvalidFeedContract(feed);
688
+ _validateTokenDecimals(token);
689
+ }
690
+
691
+ /**
692
+ * @notice Validates input parameters before setting an ERc 4626 vault.
693
+ * @dev Ensures decimals for vault and underlying assets are equal, and bounded by global invariants.
694
+ * @param vault ERC-4626 asset.
695
+ * @param underlying ERC-20 asset.
696
+ */
697
+ function _validateERC4626Vault(
698
+ address vault,
699
+ address underlying
700
+ ) internal view {
701
+ if (vault == address(0))
702
+ revert ZeroAddress("UBKOracle::_validateERC4626Vault", "vault");
703
+ if (underlying == address(0)) {
704
+ revert ZeroAddress(
705
+ "UBKOracle::_validateERC4626Vault",
706
+ "underlying"
707
+ );
708
+ }
709
+ try IERC4626(vault).asset() returns (address) {} catch {
710
+ revert InvalidERC4626Vault(vault);
711
+ }
712
+ uint8 vaultDecimals = _validateTokenDecimals(vault); // Must be between [6,18]
713
+ uint8 underlyingDecimals = _validateTokenDecimals(underlying); // Must be between [6,18]
714
+
715
+ if (vaultDecimals != underlyingDecimals) {
716
+ revert ERC4626DecimalsMismatch(
717
+ "UBKOracle::_validateERC4626Vault",
718
+ vault,
719
+ underlying
720
+ );
721
+ }
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
+ }
615
741
  }
@@ -4,18 +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 InvalidOraclePrice(address token, address feed);
20
+ error NoFallbackPrice(address token);
15
21
  error NoPriceFeed(address token);
16
- error StalePrice(address token, uint256 updatedAt, uint256 currentTime);
22
+ error OraclePaused(address oracle, uint256 timestamp);
23
+ error RecursiveResolution(address token);
17
24
  error StaleFallback(address token);
18
- error NoFallbackPrice(address token);
25
+ error StalePrice(address token, uint256 updatedAt, uint256 currentTime);
19
26
  error SuspiciousVaultRate(address vault, uint256 rate);
20
- error RecursiveResolution(address token);
21
- error OraclePaused(address oracle, uint256 timestamp);
27
+ error TokenNotSupported(address token);
@@ -0,0 +1,5 @@
1
+ {
2
+ "0.1.7": "0x37814FAA5bd659888380CBa070F098Cc0999A8cA",
3
+ "0.1.8": "0x5d4747d514B529005F4014f26068E1f4Ec47E06B",
4
+ "0.1.9": "0x04B21e27e24Ab71472690C9a09BC7A826d658668"
5
+ }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@ubk-labs/ubk-oracle",
3
- "version": "0.1.8",
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",
@@ -20,6 +21,7 @@
20
21
  "files": [
21
22
  "contracts",
22
23
  "interfaces",
24
+ "deployments",
23
25
  "README.md",
24
26
  "LICENSE",
25
27
  "package.json"
@@ -37,6 +39,6 @@
37
39
  },
38
40
  "dependencies": {
39
41
  "@chainlink/contracts": "^0.6.1",
40
- "@ubk-labs/ubk-commons": "^0.1.5"
42
+ "@ubk-labs/ubk-commons": "^0.1.7"
41
43
  }
42
44
  }