@venusprotocol/liquidity-hub 2.1.0-dev.6 → 2.1.0-dev.8

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.
Files changed (39) hide show
  1. package/README.md +17 -13
  2. package/contracts/YieldGroup/YieldGroup.sol +1 -1
  3. package/contracts/YieldGroup/YieldGroupCentrifuge.sol +7 -0
  4. package/contracts/YieldGroup/YieldGroupFRV.sol +1 -0
  5. package/contracts/YieldGroup/base/NavGuard.sol +5 -4
  6. package/contracts/YieldGroup/base/YieldGroupBase.sol +95 -9
  7. package/contracts/YieldGroup/base/YieldGroupBaseStorage.sol +10 -2
  8. package/contracts/adapters/AdapterCentrifuge.sol +16 -1
  9. package/contracts/adapters/AdapterCoreV1.sol +29 -15
  10. package/contracts/adapters/AdapterFRV.sol +17 -7
  11. package/contracts/adapters/AdapterFlux.sol +15 -3
  12. package/contracts/adapters/AdapterSpokeV1.sol +15 -3
  13. package/contracts/interfaces/IMigrator.sol +8 -6
  14. package/contracts/interfaces/INavGuard.sol +9 -8
  15. package/contracts/interfaces/IResourceAdapter.sol +12 -3
  16. package/contracts/interfaces/IYieldGroupBase.sol +56 -7
  17. package/contracts/interfaces/external/IVToken.sol +9 -0
  18. package/contracts/migrator/Migrator.sol +21 -9
  19. package/deployments/bscmainnet/AdapterCoreV1.json +26 -2
  20. package/deployments/bscmainnet/AdapterFRV.json +26 -2
  21. package/deployments/bscmainnet/AdapterFlux.json +26 -2
  22. package/deployments/bscmainnet/AdapterSpokeV1.json +26 -2
  23. package/deployments/bscmainnet/Migrator.json +28 -4
  24. package/deployments/bscmainnet/YieldGroupCoreImpl.json +69 -2
  25. package/deployments/bscmainnet/YieldGroupFRVImpl.json +69 -2
  26. package/deployments/bscmainnet/YieldGroupFluxImpl.json +69 -2
  27. package/deployments/bscmainnet/YieldGroupSpokeImpl.json +69 -2
  28. package/deployments/bscmainnet_addresses.json +9 -9
  29. package/deployments/bsctestnet/AdapterCoreV1.json +26 -2
  30. package/deployments/bsctestnet/AdapterFRV.json +26 -2
  31. package/deployments/bsctestnet/AdapterFlux.json +26 -2
  32. package/deployments/bsctestnet/AdapterSpokeV1.json +26 -2
  33. package/deployments/bsctestnet/Migrator.json +28 -4
  34. package/deployments/bsctestnet/YieldGroupCoreImpl.json +69 -2
  35. package/deployments/bsctestnet/YieldGroupFRVImpl.json +69 -2
  36. package/deployments/bsctestnet/YieldGroupFluxImpl.json +69 -2
  37. package/deployments/bsctestnet/YieldGroupSpokeImpl.json +69 -2
  38. package/deployments/bsctestnet_addresses.json +9 -9
  39. package/package.json +1 -1
@@ -7,8 +7,10 @@ pragma solidity 0.8.25;
7
7
  * @notice One-click migration from an existing Venus Core position into a Liquidity Hub. In a
8
8
  * single atomic transaction the Migrator pulls a user's Core vToken, redeems it to the
9
9
  * underlying, and deposits that into the matching Hub, minting share tokens to `receiver`.
10
- * @dev A single immutable, permissionless deployment serves every Hub — the target is chosen per
11
- * call via the `hub` argument. Two paths exist because Venus splits its markets by asset type:
10
+ * @dev A single immutable, permissionless deployment serves every registered Hub — the target is
11
+ * chosen per call via the `hub` argument and must be present in the HubRegistry, so a migration
12
+ * can only ever land in a governance-registered Hub. Two paths exist because Venus splits its
13
+ * markets by asset type:
12
14
  * ERC-20-backed markets (vUSDT, vUSDC, ...) go through {migrateFromCore}; the native market
13
15
  * (vBNB) redeems raw BNB and so has the dedicated {migrateFromCoreBNB} path that wraps to WBNB
14
16
  * before depositing into the WBNB Hub.
@@ -36,6 +38,8 @@ interface IMigrator {
36
38
  error ZeroAddress();
37
39
  /// @notice A required amount argument was zero.
38
40
  error ZeroAmount();
41
+ /// @notice The target `hub` is not a governance-registered Hub in the HubRegistry.
42
+ error HubNotRegistered(address hub);
39
43
  /// @notice The vToken's underlying does not match the Hub's asset.
40
44
  error AssetMismatch(address vTokenUnderlying, address hubAsset);
41
45
  /// @notice The Core market returned a non-zero (failure) error code on redeem.
@@ -44,8 +48,6 @@ interface IMigrator {
44
48
  error NothingReceived();
45
49
  /// @notice The minted shares were below the caller's `minShares` floor.
46
50
  error InsufficientShares(uint256 shares, uint256 minShares);
47
- /// @notice The native (vBNB → WBNB) path is unavailable: this deployment has no WBNB/vBNB wired.
48
- error BNBMigrationUnsupported();
49
51
  /// @notice Native value was received from an address other than the configured vBNB market.
50
52
  error OnlyVBNB();
51
53
 
@@ -95,8 +97,8 @@ interface IMigrator {
95
97
  /**
96
98
  * @notice Migrate a native vBNB position into the WBNB Hub.
97
99
  * @dev Caller must first `approve` this Migrator to transfer `vBNBAmount` of the configured
98
- * vBNB market. The redeemed BNB is wrapped to WBNB before deposit. Reverts unless this
99
- * deployment has WBNB/vBNB wired, `IHub(hub).asset() == WBNB`, and `shares >= minShares`.
100
+ * vBNB market. The redeemed BNB is wrapped to WBNB before deposit. Reverts unless `hub` is a
101
+ * registered WBNB Hub (`IHub(hub).asset() == WBNB`) and `shares >= minShares`.
100
102
  * This is the no-consent path — use {migrateFromCoreBNBWithConsent} to record consent.
101
103
  * @param vBNBAmount vBNB receipts to pull and redeem.
102
104
  * @param hub The WBNB Hub to deposit into.
@@ -9,8 +9,9 @@ pragma solidity 0.8.25;
9
9
  * @dev The band vouches for a value: the last counterparty figure we accepted, grown at the
10
10
  * expected rate, plus whatever we have moved in or out since. Valuation is held a gap either
11
11
  * side of that, `min(max(observed, floor), cap)`, and never reverts. The gaps are a percentage
12
- * of the counterparty's part only, so our own moves never widen them. Take everything out and
13
- * the band closes; a deposit or governance reopens it.
12
+ * of `anchor`. Our own moves shift only `centre`, so they do not widen the gaps until the next
13
+ * re-anchor, which adopts the whole position as the new `anchor`. Take everything out and the
14
+ * band closes; a deposit or governance reopens it.
14
15
  *
15
16
  * It bounds value, not price: a position marked as `quantity x price` can be inflated
16
17
  * through either factor. Value is the product plus whatever has no price at all, so one band
@@ -46,9 +47,9 @@ interface INavGuard {
46
47
  * `anchor` and `centre` are stored as of `driftFrom`, and each grows at `driftBps` from
47
48
  * there when read. A closed band has both at zero: every armed side then values the
48
49
  * position at nothing, and only a deposit or {setNavGuardSnapshot} reopens it.
49
- * @param anchor The counterparty's part of the position: the value accepted at the last
50
- * re-anchor, or forced by governance, less what withdrawals have since taken past our own
51
- * deposits. Never above `centre`. Both gaps are sized to it.
50
+ * @param anchor The whole position value accepted at the last re-anchor, or forced by
51
+ * governance, less what withdrawals have since taken past our own deposits. Never above
52
+ * `centre`. Both gaps are sized to it.
52
53
  * @param centre `anchor` plus our own deposits since. What valuation is held around.
53
54
  * @param anchoredAt When `anchor` was last set. `interval` is measured from here, and only a
54
55
  * re-anchor moves it, so our own flows can never delay or bring one forward.
@@ -124,10 +125,10 @@ interface INavGuard {
124
125
 
125
126
  /**
126
127
  * @notice We moved value into or out of a resource, and its centre moved by exactly that. The
127
- * clock is untouched, and the anchor moves only when a withdrawal reaches into the
128
- * counterparty's part.
128
+ * clock is untouched, and the anchor moves only when a withdrawal takes more than our
129
+ * own deposits since the last re-anchor.
129
130
  * @param resource Resource whose centre moved.
130
- * @param anchor The counterparty's part after the move. Zero right after a deposit means the
131
+ * @param anchor The anchor after the move. Zero right after a deposit means the
131
132
  * deposit opened the band, and the band has no width until its first re-anchor.
132
133
  * @param centre New stored centre, before drift.
133
134
  */
@@ -103,6 +103,16 @@ interface IResourceAdapter {
103
103
  */
104
104
  function totalAssets(address resource, address holder) external view returns (uint256 value);
105
105
 
106
+ /**
107
+ * @notice Underlying value of `shares` receipt tokens of `resource`, priced exactly as
108
+ * {totalAssets} prices a holder's balance. Lets the YieldGroup value the receipts it
109
+ * minted itself rather than everything its wallet happens to hold.
110
+ * @param resource Underlying yield protocol address.
111
+ * @param shares Receipt-token amount to price, in the resource's own units.
112
+ * @return value Underlying units `shares` are worth.
113
+ */
114
+ function receiptValue(address resource, uint256 shares) external view returns (uint256 value);
115
+
106
116
  /**
107
117
  * @notice Spare deposit headroom on `resource` right now (capacity remaining before the
108
118
  * resource rejects mint via its own caps or pause).
@@ -137,9 +147,8 @@ interface IResourceAdapter {
137
147
  /**
138
148
  * @notice Raw receipt-token balance `holder` owns via `resource` (vToken / fToken / FRV
139
149
  * shares), in receipt-token units — NOT underlying value.
140
- * @dev Used by `YieldGroup.removeResource` as a share-based emptiness gate. A value-based
141
- * check (`totalAssets`) rounds a small-but-non-zero receipt balance down to 0, which
142
- * would let removal orphan those receipt tokens; reading the raw balance closes that gap.
150
+ * @dev In share units so a sub-unit residual still reads as non-zero where a value read would
151
+ * round it to 0.
143
152
  * @param resource Underlying yield protocol address.
144
153
  * @param holder Address whose receipt balance to read (the YieldGroup).
145
154
  * @return shares Receipt-token units `holder` holds in this resource.
@@ -138,6 +138,16 @@ interface IYieldGroupBase {
138
138
  */
139
139
  event Swept(address indexed token, address indexed to, uint256 amount);
140
140
 
141
+ /**
142
+ * @notice Governance synced the tracked receipt balance of `resource` with what it holds, so
143
+ * receipt tokens that arrived outside the deposit path now count toward the Hub's share
144
+ * price, up to the cap the sync was given.
145
+ * @param resource Resource whose tracked balance was synced.
146
+ * @param oldShares Tracked receipt balance before the sync.
147
+ * @param newShares Tracked receipt balance after the sync.
148
+ */
149
+ event ReceiptSynced(address indexed resource, uint256 oldShares, uint256 newShares);
150
+
141
151
  // -------------------------------- Errors ----------------------------------
142
152
 
143
153
  /// @notice Caller of an `onlyHub` function was not the registered Hub.
@@ -188,9 +198,10 @@ interface IYieldGroupBase {
188
198
  error ResourceNotRegistered(address resource);
189
199
 
190
200
  /**
191
- * @notice `removeResource()` called while the resource still holds a non-zero balance.
201
+ * @notice `removeResource()` called while the YieldGroup still accounts for receipts of the
202
+ * resource (the tracked ledger for a tracking family, the wallet balance otherwise).
192
203
  * @param resource Resource attempted to be removed.
193
- * @param balance Current resource balance preventing removal.
204
+ * @param balance Accounted receipt balance preventing removal, in the resource's share units.
194
205
  */
195
206
  error ResourceHasBalance(address resource, uint256 balance);
196
207
 
@@ -246,8 +257,8 @@ interface IYieldGroupBase {
246
257
  error InvalidQueue();
247
258
 
248
259
  /**
249
- * @notice Withdraw queue omits a resource still holding receipt tokens, which the cascade would
250
- * then not visit.
260
+ * @notice Withdraw queue omits a resource whose accounted receipts are non-zero (the tracked
261
+ * ledger for a tracking family, the wallet otherwise), which the cascade would then not visit.
251
262
  * @param resource The funded resource missing from the queue.
252
263
  */
253
264
  error WithdrawQueueOmitsFundedResource(address resource);
@@ -266,6 +277,10 @@ interface IYieldGroupBase {
266
277
  /// `totalAssets` and must never be sweepable.
267
278
  error SweepProtectedAsset();
268
279
 
280
+ /// @notice `syncReceipt` was called on a family that values positions by holder, not by tracked
281
+ /// receipts (Centrifuge), where the sync would write a slot nothing reads.
282
+ error ReceiptTrackingOff();
283
+
269
284
  /**
270
285
  * @notice `sweep()` targeted a registered resource. In every family the resource address is the
271
286
  * receipt token backing `totalAssets`, so sweeping it would drain the YieldGroup.
@@ -361,7 +376,9 @@ interface IYieldGroupBase {
361
376
  function addResource(address resource, address adapter) external;
362
377
 
363
378
  /**
364
- * @notice Remove a registered resource. Requires zero balance held in that resource.
379
+ * @notice Remove a registered resource. Requires the YieldGroup to account for no receipts of it:
380
+ * the tracked ledger for a tracking family, the wallet balance otherwise. Receipts that
381
+ * arrived outside the deposit path do not block removal and are sweepable afterwards.
365
382
  * @dev ACM role `"removeResource(address)"` (VIP). Also removes the resource from both
366
383
  * inner queues via swap-and-pop. Emits {ResourceRemoved}.
367
384
  * @param resource Resource to remove.
@@ -433,6 +450,27 @@ interface IYieldGroupBase {
433
450
  */
434
451
  function sweep(address token, address to) external;
435
452
 
453
+ /**
454
+ * @notice Set the tracked receipt balance of `resource` to what it holds, adding at most
455
+ * `maxAdded`. This admits receipt tokens that arrived outside the deposit path (a
456
+ * donation, a mistransfer) into the Hub's share price; until then they sit on the
457
+ * YieldGroup uncounted.
458
+ * @dev ACM role `"syncReceipt(address,uint256)"` (VIP). Emits {ReceiptSynced}. Reverts
459
+ * {ReceiptTrackingOff} on a family that does not track receipts.
460
+ *
461
+ * `maxAdded` caps the sync at the amount governance reviewed. A VIP executes days after it
462
+ * is proposed, and anything sent in meanwhile, including over-priced receipts from a market
463
+ * carrying bad debt, stays uncounted above the cap. It is a cap rather than an exact match,
464
+ * so a single extra wei sent in before execution cannot make the sync revert.
465
+ *
466
+ * `type(uint256).max` syncs the whole wallet. The upgrade that introduced tracking needs it:
467
+ * every tracked balance starts at 0 there, and the wallet at execution cannot be known when
468
+ * the VIP is proposed. The old code already priced the whole wallet, so it admits nothing new.
469
+ * @param resource Registered resource to sync.
470
+ * @param maxAdded Most receipts this sync may add to the tracked balance.
471
+ */
472
+ function syncReceipt(address resource, uint256 maxAdded) external;
473
+
436
474
  // ---------------------------------- Views --------------------------------
437
475
 
438
476
  /**
@@ -442,9 +480,11 @@ interface IYieldGroupBase {
442
480
  function asset() external view returns (address underlying);
443
481
 
444
482
  /**
445
- * @notice Sum of `asset` held across all of this YieldGroup's underlying vaults.
483
+ * @notice Underlying value of the receipts this YieldGroup accounts for across its resources,
484
+ * plus its idle `asset` balance. A tracking family prices only the receipts its own
485
+ * deposits minted; Centrifuge prices its whole wallet.
446
486
  * @dev Hub sums `totalAssets()` over its registered YieldGroups to compute its own totalAssets().
447
- * @return total Asset units currently held by the YieldGroup.
487
+ * @return total Asset units the YieldGroup accounts for.
448
488
  */
449
489
  function totalAssets() external view returns (uint256 total);
450
490
 
@@ -502,6 +542,15 @@ interface IYieldGroupBase {
502
542
  */
503
543
  function resourceConfig(address resource) external view returns (bool registered, bool paused, address adapter);
504
544
 
545
+ /**
546
+ * @notice Receipt tokens of `resource` that count toward `totalAssets()`: those this YieldGroup
547
+ * minted through its own deposits, net of what it redeemed. Always 0 for a family that
548
+ * does not track receipts (Centrifuge), which prices its wallet instead.
549
+ * @param resource Resource to look up.
550
+ * @return shares Tracked receipt balance, in the resource's own share units.
551
+ */
552
+ function trackedReceipt(address resource) external view returns (uint256 shares);
553
+
505
554
  /// @notice Current inner deposit-routing order.
506
555
  /// @return queue Storage copy of the inner deposit queue.
507
556
  function innerDepositQueue() external view returns (address[] memory queue);
@@ -104,6 +104,15 @@ interface IVToken {
104
104
  */
105
105
  function getCash() external view returns (uint256 cash);
106
106
 
107
+ /**
108
+ * @notice Protocol reserves held inside `getCash()`.
109
+ * @dev `accrueInterest` sends them out of cash to the ProtocolShareReserve once
110
+ * `reduceReservesBlockDelta` blocks have elapsed, so a redeem can only count on
111
+ * `getCash() - totalReserves()`.
112
+ * @return reserves Underlying units reserved for the protocol.
113
+ */
114
+ function totalReserves() external view returns (uint256 reserves);
115
+
107
116
  /**
108
117
  * @notice The ERC-20 underlying token. Reverts for vBNB (which has no `underlying`
109
118
  * accessor); the Core Yield Group v1 uses this revert as a guard against vBNB
@@ -6,6 +6,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s
6
6
  import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
7
7
 
8
8
  import { IHub } from "../interfaces/IHub.sol";
9
+ import { IHubRegistry } from "../interfaces/IHubRegistry.sol";
9
10
  import { IMigrator } from "../interfaces/IMigrator.sol";
10
11
  import { IVBep20 } from "../interfaces/external/IVBep20.sol";
11
12
  import { IWBNB } from "../interfaces/external/IWBNB.sol";
@@ -14,12 +15,16 @@ import { IWBNB } from "../interfaces/external/IWBNB.sol";
14
15
  * @title Migrator
15
16
  * @author Venus
16
17
  * @notice One-click migration from a Venus Core position into a Liquidity Hub. A single immutable,
17
- * permissionless deployment serves every Hub; the target Hub is supplied per call.
18
+ * permissionless deployment serves every registered Hub; the target Hub is supplied per call
19
+ * and must be present in the HubRegistry.
18
20
  * @dev Stateless by design — no proxy, no admin, no funds held between calls. Each migration is
19
21
  * atomic: pull the user's vToken, redeem it to the underlying, deposit that into the Hub, and
20
22
  * mint shares straight to the receiver. If any leg fails the whole call reverts and the user
21
23
  * keeps their vToken.
22
24
  *
25
+ * The target `hub` is checked against the immutable {HUB_REGISTRY} before any funds move, so a
26
+ * migration can only land in a Hub governance has registered.
27
+ *
23
28
  * Accounting is done by balance delta, never by a self-reported amount: Core `redeem` returns
24
29
  * a Compound error code (not the redeemed amount) and silently nets out any Comptroller
25
30
  * treasury fee, so the Migrator measures what actually arrived and deposits exactly that. The
@@ -34,16 +39,24 @@ import { IWBNB } from "../interfaces/external/IWBNB.sol";
34
39
  contract Migrator is IMigrator, ReentrancyGuard {
35
40
  using SafeERC20 for IERC20;
36
41
 
37
- /// @notice Canonical wrapped-native token; `address(0)` disables the native path.
42
+ /// @notice Governance-curated directory of valid Hubs.
43
+ IHubRegistry public immutable HUB_REGISTRY;
44
+ /// @notice Canonical wrapped-native token (WBNB).
38
45
  IWBNB public immutable WBNB;
39
- /// @notice Canonical Venus native market (vBNB); `address(0)` disables the native path.
46
+ /// @notice Canonical Venus native market (vBNB).
40
47
  IVBep20 public immutable VBNB;
41
48
 
42
49
  /**
43
- * @param wbnb_ Wrapped-native token, or `address(0)` on chains/deployments with no WBNB Hub.
44
- * @param vbnb_ Venus native market (vBNB), or `address(0)` to leave the native path disabled.
50
+ * @param wbnb_ Wrapped-native token (WBNB). Mandatory; the constructor reverts on the zero address.
51
+ * @param vbnb_ Venus native market (vBNB). Mandatory; the constructor reverts on the zero address.
52
+ * @param hubRegistry_ The HubRegistry every migration target is validated against. Mandatory;
53
+ * the constructor reverts on the zero address, since without it no Hub would be accepted.
45
54
  */
46
- constructor(IWBNB wbnb_, IVBep20 vbnb_) {
55
+ constructor(IWBNB wbnb_, IVBep20 vbnb_, IHubRegistry hubRegistry_) {
56
+ if (address(wbnb_) == address(0) || address(vbnb_) == address(0) || address(hubRegistry_) == address(0)) {
57
+ revert ZeroAddress();
58
+ }
59
+ HUB_REGISTRY = hubRegistry_;
47
60
  WBNB = wbnb_;
48
61
  VBNB = vbnb_;
49
62
  }
@@ -111,6 +124,7 @@ contract Migrator is IMigrator, ReentrancyGuard {
111
124
  revert ZeroAddress();
112
125
  }
113
126
  if (vTokenAmount == 0) revert ZeroAmount();
127
+ if (!HUB_REGISTRY.isHub(hub)) revert HubNotRegistered(hub);
114
128
 
115
129
  address asset = IHub(hub).asset();
116
130
  address vTokenUnderlying = IVBep20(vToken).underlying();
@@ -135,11 +149,9 @@ contract Migrator is IMigrator, ReentrancyGuard {
135
149
  private
136
150
  returns (uint256 shares)
137
151
  {
138
- if (address(WBNB) == address(0) || address(VBNB) == address(0)) {
139
- revert BNBMigrationUnsupported();
140
- }
141
152
  if (hub == address(0) || receiver == address(0)) revert ZeroAddress();
142
153
  if (vBNBAmount == 0) revert ZeroAmount();
154
+ if (!HUB_REGISTRY.isHub(hub)) revert HubNotRegistered(hub);
143
155
 
144
156
  address asset = IHub(hub).asset();
145
157
  if (asset != address(WBNB)) revert AssetMismatch(address(WBNB), asset);
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0xa061cC2F62BDa2D6bA53Fb98847aD9822DA085dd",
3
- "block": 123325056,
2
+ "address": "0x0f62927d18Fd35712622C2c6C3F730EB8a18b71B",
3
+ "block": 132740470,
4
4
  "chainId": 56,
5
5
  "contract": "AdapterCoreV1",
6
6
  "abi": [
@@ -158,6 +158,30 @@
158
158
  ],
159
159
  "stateMutability": "view"
160
160
  },
161
+ {
162
+ "type": "function",
163
+ "name": "receiptValue",
164
+ "inputs": [
165
+ {
166
+ "name": "resource",
167
+ "type": "address",
168
+ "internalType": "address"
169
+ },
170
+ {
171
+ "name": "vBal",
172
+ "type": "uint256",
173
+ "internalType": "uint256"
174
+ }
175
+ ],
176
+ "outputs": [
177
+ {
178
+ "name": "",
179
+ "type": "uint256",
180
+ "internalType": "uint256"
181
+ }
182
+ ],
183
+ "stateMutability": "view"
184
+ },
161
185
  {
162
186
  "type": "function",
163
187
  "name": "resourceName",
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0x1824caA965Ac05ae5C9C2819e045337e2cF5657c",
3
- "block": 123325056,
2
+ "address": "0x40fDc0fef94D607EE4341230afb09bcDB0B949E2",
3
+ "block": 132740470,
4
4
  "chainId": 56,
5
5
  "contract": "AdapterFRV",
6
6
  "abi": [
@@ -132,6 +132,30 @@
132
132
  ],
133
133
  "stateMutability": "view"
134
134
  },
135
+ {
136
+ "type": "function",
137
+ "name": "receiptValue",
138
+ "inputs": [
139
+ {
140
+ "name": "resource",
141
+ "type": "address",
142
+ "internalType": "address"
143
+ },
144
+ {
145
+ "name": "shares",
146
+ "type": "uint256",
147
+ "internalType": "uint256"
148
+ }
149
+ ],
150
+ "outputs": [
151
+ {
152
+ "name": "",
153
+ "type": "uint256",
154
+ "internalType": "uint256"
155
+ }
156
+ ],
157
+ "stateMutability": "view"
158
+ },
135
159
  {
136
160
  "type": "function",
137
161
  "name": "resourceName",
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0x9a1a7F6aebA4a1A3e85Ae1Dba90a7A2A52803404",
3
- "block": 123325056,
2
+ "address": "0x4Afb747ce8dDef689d5484FFdfB69Ac8bC7cAc8B",
3
+ "block": 132740470,
4
4
  "chainId": 56,
5
5
  "contract": "AdapterFlux",
6
6
  "abi": [
@@ -151,6 +151,30 @@
151
151
  ],
152
152
  "stateMutability": "view"
153
153
  },
154
+ {
155
+ "type": "function",
156
+ "name": "receiptValue",
157
+ "inputs": [
158
+ {
159
+ "name": "resource",
160
+ "type": "address",
161
+ "internalType": "address"
162
+ },
163
+ {
164
+ "name": "shares",
165
+ "type": "uint256",
166
+ "internalType": "uint256"
167
+ }
168
+ ],
169
+ "outputs": [
170
+ {
171
+ "name": "",
172
+ "type": "uint256",
173
+ "internalType": "uint256"
174
+ }
175
+ ],
176
+ "stateMutability": "view"
177
+ },
154
178
  {
155
179
  "type": "function",
156
180
  "name": "resourceName",
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0x231915FfE3e3A6Be09B0E5c73EFA2F1a4FF8Aa69",
3
- "block": 127748551,
2
+ "address": "0xD08596E58325724C824100bA87f2470493Fe342d",
3
+ "block": 132740470,
4
4
  "chainId": 56,
5
5
  "contract": "AdapterSpokeV1",
6
6
  "abi": [
@@ -158,6 +158,30 @@
158
158
  ],
159
159
  "stateMutability": "view"
160
160
  },
161
+ {
162
+ "type": "function",
163
+ "name": "receiptValue",
164
+ "inputs": [
165
+ {
166
+ "name": "resource",
167
+ "type": "address",
168
+ "internalType": "address"
169
+ },
170
+ {
171
+ "name": "vBal",
172
+ "type": "uint256",
173
+ "internalType": "uint256"
174
+ }
175
+ ],
176
+ "outputs": [
177
+ {
178
+ "name": "",
179
+ "type": "uint256",
180
+ "internalType": "uint256"
181
+ }
182
+ ],
183
+ "stateMutability": "view"
184
+ },
161
185
  {
162
186
  "type": "function",
163
187
  "name": "resourceName",
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0xfe6b8BEf1215C19Cd247FbF495ef560932F1Eb9B",
3
- "block": 112781054,
2
+ "address": "0xb0D77DC86d4E6a8282eECF3d4d456B3b94F2a7aD",
3
+ "block": 115268335,
4
4
  "chainId": 56,
5
5
  "contract": "Migrator",
6
6
  "abi": [
@@ -16,6 +16,11 @@
16
16
  "name": "vbnb_",
17
17
  "type": "address",
18
18
  "internalType": "contract IVBep20"
19
+ },
20
+ {
21
+ "name": "hubRegistry_",
22
+ "type": "address",
23
+ "internalType": "contract IHubRegistry"
19
24
  }
20
25
  ],
21
26
  "stateMutability": "nonpayable"
@@ -24,6 +29,19 @@
24
29
  "type": "receive",
25
30
  "stateMutability": "payable"
26
31
  },
32
+ {
33
+ "type": "function",
34
+ "name": "HUB_REGISTRY",
35
+ "inputs": [],
36
+ "outputs": [
37
+ {
38
+ "name": "",
39
+ "type": "address",
40
+ "internalType": "contract IHubRegistry"
41
+ }
42
+ ],
43
+ "stateMutability": "view"
44
+ },
27
45
  {
28
46
  "type": "function",
29
47
  "name": "VBNB",
@@ -292,8 +310,14 @@
292
310
  },
293
311
  {
294
312
  "type": "error",
295
- "name": "BNBMigrationUnsupported",
296
- "inputs": []
313
+ "name": "HubNotRegistered",
314
+ "inputs": [
315
+ {
316
+ "name": "hub",
317
+ "type": "address",
318
+ "internalType": "address"
319
+ }
320
+ ]
297
321
  },
298
322
  {
299
323
  "type": "error",
@@ -1,6 +1,6 @@
1
1
  {
2
- "address": "0x3BccED778CAaf97AE8ff8Bedc16d2165aA15771b",
3
- "block": 112779813,
2
+ "address": "0xedB1c751Eb03274e9D15D0609B4593CC113fB09F",
3
+ "block": 132740470,
4
4
  "chainId": 56,
5
5
  "contract": "YieldGroup",
6
6
  "abi": [
@@ -460,6 +460,24 @@
460
460
  "outputs": [],
461
461
  "stateMutability": "nonpayable"
462
462
  },
463
+ {
464
+ "type": "function",
465
+ "name": "syncReceipt",
466
+ "inputs": [
467
+ {
468
+ "name": "resource",
469
+ "type": "address",
470
+ "internalType": "address"
471
+ },
472
+ {
473
+ "name": "maxAdded",
474
+ "type": "uint256",
475
+ "internalType": "uint256"
476
+ }
477
+ ],
478
+ "outputs": [],
479
+ "stateMutability": "nonpayable"
480
+ },
463
481
  {
464
482
  "type": "function",
465
483
  "name": "totalAssets",
@@ -473,6 +491,25 @@
473
491
  ],
474
492
  "stateMutability": "view"
475
493
  },
494
+ {
495
+ "type": "function",
496
+ "name": "trackedReceipt",
497
+ "inputs": [
498
+ {
499
+ "name": "resource",
500
+ "type": "address",
501
+ "internalType": "address"
502
+ }
503
+ ],
504
+ "outputs": [
505
+ {
506
+ "name": "",
507
+ "type": "uint256",
508
+ "internalType": "uint256"
509
+ }
510
+ ],
511
+ "stateMutability": "view"
512
+ },
476
513
  {
477
514
  "type": "function",
478
515
  "name": "unpauseResource",
@@ -622,6 +659,31 @@
622
659
  ],
623
660
  "anonymous": false
624
661
  },
662
+ {
663
+ "type": "event",
664
+ "name": "ReceiptSynced",
665
+ "inputs": [
666
+ {
667
+ "name": "resource",
668
+ "type": "address",
669
+ "indexed": true,
670
+ "internalType": "address"
671
+ },
672
+ {
673
+ "name": "oldShares",
674
+ "type": "uint256",
675
+ "indexed": false,
676
+ "internalType": "uint256"
677
+ },
678
+ {
679
+ "name": "newShares",
680
+ "type": "uint256",
681
+ "indexed": false,
682
+ "internalType": "uint256"
683
+ }
684
+ ],
685
+ "anonymous": false
686
+ },
625
687
  {
626
688
  "type": "event",
627
689
  "name": "ResourceAccrualFailed",
@@ -897,6 +959,11 @@
897
959
  "name": "OnlySelf",
898
960
  "inputs": []
899
961
  },
962
+ {
963
+ "type": "error",
964
+ "name": "ReceiptTrackingOff",
965
+ "inputs": []
966
+ },
900
967
  {
901
968
  "type": "error",
902
969
  "name": "ResourceAlreadyRegistered",