@venusprotocol/liquidity-hub 2.1.0-dev.4 → 2.1.0-dev.5
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.
- package/README.md +111 -30
- package/contracts/Hub/Hub.sol +71 -63
- package/contracts/adapters/AdapterCentrifuge.sol +5 -0
- package/contracts/adapters/AdapterCoreV1.sol +6 -0
- package/contracts/adapters/AdapterFRV.sol +27 -7
- package/contracts/adapters/AdapterFlux.sol +6 -0
- package/contracts/adapters/AdapterSpokeV1.sol +428 -0
- package/contracts/interfaces/IHub.sol +6 -0
- package/contracts/interfaces/IHubLens.sol +71 -0
- package/contracts/interfaces/IResourceAdapter.sol +23 -7
- package/contracts/interfaces/IYieldGroupBase.sol +6 -1
- package/contracts/interfaces/external/ISpokeComptroller.sol +69 -0
- package/contracts/interfaces/external/IVTokenIsolated.sol +153 -0
- package/contracts/lens/HubCapacityMath.sol +610 -0
- package/contracts/lens/HubLens.sol +311 -0
- package/deployments/bscmainnet/AdapterCentrifuge.json +21 -2
- package/deployments/bscmainnet/AdapterCoreV1.json +21 -2
- package/deployments/bscmainnet/AdapterFRV.json +21 -2
- package/deployments/bscmainnet/AdapterFlux.json +21 -2
- package/deployments/bscmainnet/AdapterSpokeV1.json +339 -0
- package/deployments/bscmainnet/HubImpl.json +16 -3
- package/deployments/bscmainnet/HubLens.json +89 -0
- package/deployments/bscmainnet/SpokeBeacon.json +110 -0
- package/deployments/bscmainnet/SpokeSource_U.json +1083 -0
- package/deployments/bscmainnet/SpokeSource_USDC.json +1083 -0
- package/deployments/bscmainnet/SpokeSource_USDT.json +1083 -0
- package/deployments/bscmainnet/YieldGroupSpokeImpl.json +1083 -0
- package/deployments/bscmainnet_addresses.json +13 -6
- package/deployments/bsctestnet/AdapterCentrifuge.json +21 -2
- package/deployments/bsctestnet/AdapterCoreV1.json +21 -2
- package/deployments/bsctestnet/AdapterFRV.json +21 -2
- package/deployments/bsctestnet/AdapterFlux.json +21 -2
- package/deployments/bsctestnet/AdapterSpokeV1.json +339 -0
- package/deployments/bsctestnet/HubImpl.json +16 -3
- package/deployments/bsctestnet/HubLens.json +89 -0
- package/deployments/bsctestnet/SpokeBeacon.json +110 -0
- package/deployments/bsctestnet/SpokeSource_USDT.json +1083 -0
- package/deployments/bsctestnet/YieldGroupSpokeImpl.json +1083 -0
- package/deployments/bsctestnet_addresses.json +11 -6
- package/package.json +1 -1
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.25;
|
|
3
|
+
|
|
4
|
+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
+
|
|
6
|
+
import { IHub } from "../interfaces/IHub.sol";
|
|
7
|
+
import { IHubLens } from "../interfaces/IHubLens.sol";
|
|
8
|
+
import { IResourceAdapter } from "../interfaces/IResourceAdapter.sol";
|
|
9
|
+
import { IYieldGroupBase } from "../interfaces/IYieldGroupBase.sol";
|
|
10
|
+
import { IFRVVault } from "../interfaces/external/IFRVVault.sol";
|
|
11
|
+
import { HubCapacityMath } from "./HubCapacityMath.sol";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @title HubLens
|
|
15
|
+
* @author Venus
|
|
16
|
+
* @notice Off-chain read surface for the {Hub}: deposit capacity and blended yield.
|
|
17
|
+
* @dev Stateless and immutable — no storage, no owner, no initializer, no proxy. The Hub is a call
|
|
18
|
+
* parameter rather than a stored address, so a single deployment serves `Hub_U`, `Hub_USDC`,
|
|
19
|
+
* `Hub_USDT` and every Hub added later. Nothing on the Hub points at this contract, so a new
|
|
20
|
+
* version is deployed rather than upgraded.
|
|
21
|
+
*
|
|
22
|
+
* Quantity views fail open per YieldGroup, mirroring the cascade: a YieldGroup whose
|
|
23
|
+
* `maxDeposit()` or `spotAPYBps()` reverts contributes 0 rather than bricking the whole view.
|
|
24
|
+
* NAV fails closed, inherited rather than re-implemented — every function here reads
|
|
25
|
+
* `Hub.totalAssets()`, which deliberately does NOT isolate a YieldGroup whose `totalAssets()`
|
|
26
|
+
* reverts, because a capacity or yield figure computed against a wrong NAV is worse than no
|
|
27
|
+
* figure at all.
|
|
28
|
+
*/
|
|
29
|
+
contract HubLens is IHubLens {
|
|
30
|
+
/// @dev Accrual margin trimmed off each YieldGroup's room: `balance / 10_000`, i.e. 0.01%. Sized
|
|
31
|
+
/// on the balance, not on the room, because the interest a deposit settles scales with what
|
|
32
|
+
/// the group holds. 0.01% is about nine hours of interest at 10% APY, against a mark that
|
|
33
|
+
/// goes stale only between two accruals of the venue behind it.
|
|
34
|
+
uint256 private constant ACCRUAL_MARGIN_DIVISOR = 10_000;
|
|
35
|
+
|
|
36
|
+
/// @dev ABI size of `IFRVVault.config()`: nine static words. Anything else is not an FRV vault.
|
|
37
|
+
uint256 private constant FRV_CONFIG_SIZE = 9 * 32;
|
|
38
|
+
|
|
39
|
+
/// @inheritdoc IHubLens
|
|
40
|
+
function maxDeposit(address hub) public view override returns (uint256 assets) {
|
|
41
|
+
if (IHub(hub).hubPaused()) return 0;
|
|
42
|
+
(address[] memory yieldGroups, HubCapacityMath.GroupInput[] memory groups, uint256 hubTotalAssets) =
|
|
43
|
+
_readDepositQueue(hub);
|
|
44
|
+
(HubCapacityMath.ResourceFloor[][] memory floors, bool floored) = _readFloors(yieldGroups);
|
|
45
|
+
if (floored) {
|
|
46
|
+
(assets,,) = _routable(hub, groups, floors, hubTotalAssets, false);
|
|
47
|
+
} else {
|
|
48
|
+
(assets,) = HubCapacityMath.trimmedCapacity(groups, hubTotalAssets, ACCRUAL_MARGIN_DIVISOR);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// @inheritdoc IHubLens
|
|
53
|
+
/// @dev Trimmed a second time: the interest the deposit settles also raises the share price it
|
|
54
|
+
/// prices the mint at, so these shares convert to more assets than they do here.
|
|
55
|
+
function maxMint(address hub) external view override returns (uint256 shares) {
|
|
56
|
+
if (IHub(hub).hubPaused()) return 0;
|
|
57
|
+
(address[] memory yieldGroups, HubCapacityMath.GroupInput[] memory groups, uint256 hubTotalAssets) =
|
|
58
|
+
_readDepositQueue(hub);
|
|
59
|
+
(HubCapacityMath.ResourceFloor[][] memory floors, bool floored) = _readFloors(yieldGroups);
|
|
60
|
+
if (floored) {
|
|
61
|
+
(shares,,) = _routable(hub, groups, floors, hubTotalAssets, true);
|
|
62
|
+
return shares;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
uint256 budget = HubCapacityMath.doubleTrimmedCapacity(groups, hubTotalAssets, ACCRUAL_MARGIN_DIVISOR);
|
|
66
|
+
|
|
67
|
+
// `mint` charges `previewMint`, which rounds the assets back up, but no give-back is owed:
|
|
68
|
+
// the floor here already sheds more than that round-up asks for, so `previewMint(shares)`
|
|
69
|
+
// never passes `budget`. Both directions price off the same supply and assets.
|
|
70
|
+
shares = IHub(hub).convertToShares(budget);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// @inheritdoc IHubLens
|
|
74
|
+
function depositCapacityBreakdown(address hub)
|
|
75
|
+
external
|
|
76
|
+
view
|
|
77
|
+
override
|
|
78
|
+
returns (address[] memory groups, uint256[] memory room)
|
|
79
|
+
{
|
|
80
|
+
if (IHub(hub).hubPaused()) return (groups, room);
|
|
81
|
+
HubCapacityMath.GroupInput[] memory inputs;
|
|
82
|
+
uint256 hubTotalAssets;
|
|
83
|
+
(groups, inputs, hubTotalAssets) = _readDepositQueue(hub);
|
|
84
|
+
|
|
85
|
+
// Split at the trimmed total, not the untrimmed one: the caps shrink with the deposit, so
|
|
86
|
+
// rooms solved for the untrimmed figure overstate the percentage-bound groups.
|
|
87
|
+
(HubCapacityMath.ResourceFloor[][] memory floors, bool floored) = _readFloors(groups);
|
|
88
|
+
if (floored) {
|
|
89
|
+
(,, room) = _routable(hub, inputs, floors, hubTotalAssets, false);
|
|
90
|
+
} else {
|
|
91
|
+
(, room) = HubCapacityMath.trimmedCapacity(inputs, hubTotalAssets, ACCRUAL_MARGIN_DIVISOR);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// @inheritdoc IHubLens
|
|
96
|
+
function spotAPYBps(address hub) external view override returns (uint64 apyBps) {
|
|
97
|
+
// Read first: this is `Σ YieldGroup.totalAssets()` plus Hub idle, and it reverts if any
|
|
98
|
+
// registered YieldGroup cannot be valued — the same list this loop walks, so a per-group
|
|
99
|
+
// guard below would never fire.
|
|
100
|
+
uint256 hubTotalAssets = IHub(hub).totalAssets();
|
|
101
|
+
if (hubTotalAssets == 0) return 0;
|
|
102
|
+
|
|
103
|
+
address[] memory yieldGroups = IHub(hub).registeredYieldGroups();
|
|
104
|
+
uint256 weighted;
|
|
105
|
+
|
|
106
|
+
for (uint256 i; i < yieldGroups.length; ++i) {
|
|
107
|
+
address yieldGroup = yieldGroups[i];
|
|
108
|
+
|
|
109
|
+
// Weight by the invested part alone. A YieldGroup averages its rate over its
|
|
110
|
+
// resources, while its `totalAssets()` also counts asset sitting on the YieldGroup
|
|
111
|
+
// itself, which earns nothing: weighting by the total would pay that idle the rate.
|
|
112
|
+
uint256 balance = IYieldGroupBase(yieldGroup).totalAssets();
|
|
113
|
+
uint256 idle = IERC20(IYieldGroupBase(yieldGroup).asset()).balanceOf(yieldGroup);
|
|
114
|
+
uint256 invested = balance > idle ? balance - idle : 0;
|
|
115
|
+
if (invested == 0) continue;
|
|
116
|
+
|
|
117
|
+
try IYieldGroupBase(yieldGroup).spotAPYBps() returns (uint64 v) {
|
|
118
|
+
weighted += uint256(v) * invested;
|
|
119
|
+
} catch {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Denominator is the Hub's whole TVL, not the sum of the balances weighted above, so Hub
|
|
125
|
+
// idle and any skipped YieldGroup dilute the figure at 0% instead of vanishing from it.
|
|
126
|
+
uint256 blended = weighted / hubTotalAssets;
|
|
127
|
+
return blended > type(uint64).max ? type(uint64).max : uint64(blended);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================== Private =================================
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @dev The largest trimmed figure the Hub routes in full when a YieldGroup has floored
|
|
134
|
+
* resources. `YieldGroupBase.maxDeposit()` checks each floor against the resource's own
|
|
135
|
+
* room, but the Hub cap and the inner queue can shrink the leg afterwards, so the solve's
|
|
136
|
+
* figure can land under a floor and revert. Offer the solve each floored YieldGroup's
|
|
137
|
+
* room candidates, largest first, and keep the first figure whose dry run routes in full.
|
|
138
|
+
* A failed dry run steps down the first YieldGroup that skipped part of its leg.
|
|
139
|
+
* @return amount Assets, or shares when `forMint`.
|
|
140
|
+
* @return assets Assets the Hub would route: `amount`, or `previewMint(amount)`.
|
|
141
|
+
* @return placed Per-YieldGroup amount placed by that routing.
|
|
142
|
+
*/
|
|
143
|
+
function _routable(
|
|
144
|
+
address hub,
|
|
145
|
+
HubCapacityMath.GroupInput[] memory groups,
|
|
146
|
+
HubCapacityMath.ResourceFloor[][] memory floors,
|
|
147
|
+
uint256 hubTotalAssets,
|
|
148
|
+
bool forMint
|
|
149
|
+
) private view returns (uint256 amount, uint256 assets, uint256[] memory placed) {
|
|
150
|
+
uint256 n = groups.length;
|
|
151
|
+
HubCapacityMath.GroupInput[] memory offered = new HubCapacityMath.GroupInput[](n);
|
|
152
|
+
uint256[][] memory candidates = new uint256[][](n);
|
|
153
|
+
uint256[] memory pick = new uint256[](n);
|
|
154
|
+
uint256 tries = 1;
|
|
155
|
+
|
|
156
|
+
for (uint256 i; i < n; ++i) {
|
|
157
|
+
HubCapacityMath.GroupInput memory g = groups[i];
|
|
158
|
+
offered[i] = HubCapacityMath.GroupInput({
|
|
159
|
+
balance: g.balance,
|
|
160
|
+
venueRoom: g.venueRoom,
|
|
161
|
+
absoluteCap: g.absoluteCap,
|
|
162
|
+
percentageCapBps: g.percentageCapBps
|
|
163
|
+
});
|
|
164
|
+
if (floors[i].length != 0) {
|
|
165
|
+
candidates[i] = HubCapacityMath.roomCandidates(floors[i], g.venueRoom);
|
|
166
|
+
offered[i].venueRoom = candidates[i][0];
|
|
167
|
+
tries += candidates[i].length;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (uint256 t; t < tries; ++t) {
|
|
172
|
+
if (forMint) {
|
|
173
|
+
uint256 budget = HubCapacityMath.doubleTrimmedCapacity(offered, hubTotalAssets, ACCRUAL_MARGIN_DIVISOR);
|
|
174
|
+
amount = IHub(hub).convertToShares(budget);
|
|
175
|
+
assets = IHub(hub).previewMint(amount);
|
|
176
|
+
} else {
|
|
177
|
+
(amount,) = HubCapacityMath.trimmedCapacity(offered, hubTotalAssets, ACCRUAL_MARGIN_DIVISOR);
|
|
178
|
+
assets = amount;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
uint256 left;
|
|
182
|
+
bool[] memory short;
|
|
183
|
+
(left, placed, short) = HubCapacityMath.route(groups, floors, hubTotalAssets, assets);
|
|
184
|
+
if (left == 0) return (amount, assets, placed);
|
|
185
|
+
|
|
186
|
+
uint256 i;
|
|
187
|
+
while (i < n && !(short[i] && pick[i] + 1 < candidates[i].length)) ++i;
|
|
188
|
+
if (i == n) break;
|
|
189
|
+
offered[i].venueRoom = candidates[i][++pick[i]];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return (0, 0, new uint256[](n));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/// @dev Per YieldGroup, its unpaused inner deposit-queue resources with their room and floor,
|
|
196
|
+
/// or empty when none has a floor. `floored` is true when any YieldGroup has one. Room is
|
|
197
|
+
/// the adapter's raw `maxDeposit`, which is what `YieldGroupFRV` deposits against.
|
|
198
|
+
function _readFloors(address[] memory groups)
|
|
199
|
+
private
|
|
200
|
+
view
|
|
201
|
+
returns (HubCapacityMath.ResourceFloor[][] memory floors, bool floored)
|
|
202
|
+
{
|
|
203
|
+
floors = new HubCapacityMath.ResourceFloor[][](groups.length);
|
|
204
|
+
for (uint256 i; i < groups.length; ++i) {
|
|
205
|
+
floors[i] = _readGroupFloors(groups[i]);
|
|
206
|
+
if (floors[i].length != 0) floored = true;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function _readGroupFloors(address yieldGroup) private view returns (HubCapacityMath.ResourceFloor[] memory floors) {
|
|
211
|
+
address[] memory queue;
|
|
212
|
+
try IYieldGroupBase(yieldGroup).innerDepositQueue() returns (address[] memory q) {
|
|
213
|
+
queue = q;
|
|
214
|
+
} catch {
|
|
215
|
+
return floors;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
HubCapacityMath.ResourceFloor[] memory buffer = new HubCapacityMath.ResourceFloor[](queue.length);
|
|
219
|
+
uint256 count;
|
|
220
|
+
bool anyFloor;
|
|
221
|
+
for (uint256 k; k < queue.length; ++k) {
|
|
222
|
+
address resource = queue[k];
|
|
223
|
+
address adapter;
|
|
224
|
+
try IYieldGroupBase(yieldGroup).resourceConfig(resource) returns (bool registered, bool paused, address a) {
|
|
225
|
+
if (!registered || paused) continue;
|
|
226
|
+
adapter = a;
|
|
227
|
+
} catch {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
uint256 room;
|
|
232
|
+
try IResourceAdapter(adapter).maxDeposit(resource) returns (uint256 v) {
|
|
233
|
+
room = v;
|
|
234
|
+
} catch {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
uint256 minDeposit = _minDepositOf(resource);
|
|
239
|
+
if (minDeposit != 0) anyFloor = true;
|
|
240
|
+
buffer[count++] = HubCapacityMath.ResourceFloor({ room: room, minDeposit: minDeposit });
|
|
241
|
+
}
|
|
242
|
+
if (!anyFloor) return floors;
|
|
243
|
+
|
|
244
|
+
floors = new HubCapacityMath.ResourceFloor[](count);
|
|
245
|
+
for (uint256 k; k < count; ++k) {
|
|
246
|
+
floors[k] = buffer[k];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/// @dev `minSupplierDeposit` of an FRV vault, 0 for any resource that is not one. A raw
|
|
251
|
+
/// staticcall, so a vToken or fToken without `config()` reads as no floor instead of
|
|
252
|
+
/// reverting the view.
|
|
253
|
+
function _minDepositOf(address resource) private view returns (uint256) {
|
|
254
|
+
(bool ok, bytes memory data) = resource.staticcall(abi.encodeCall(IFRVVault.config, ()));
|
|
255
|
+
if (!ok || data.length != FRV_CONFIG_SIZE) return 0;
|
|
256
|
+
return abi.decode(data, (IFRVVault.FRVVaultConfig)).minSupplierDeposit;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// @dev Read the deposit queue down to what {HubCapacityMath} needs. Sourced from that queue,
|
|
260
|
+
/// so a registered but unqueued YieldGroup is out of scope here, unlike {spotAPYBps}.
|
|
261
|
+
/// Drops every YieldGroup the cascade would skip — unregistered, paused, or failing either
|
|
262
|
+
/// view — so what it leaves out is immovable TVL, which the math derives from
|
|
263
|
+
/// `hubTotalAssets`.
|
|
264
|
+
function _readDepositQueue(address hub)
|
|
265
|
+
private
|
|
266
|
+
view
|
|
267
|
+
returns (address[] memory groups, HubCapacityMath.GroupInput[] memory inputs, uint256 hubTotalAssets)
|
|
268
|
+
{
|
|
269
|
+
// Read first, so a YieldGroup that cannot be valued halts here rather than being silently
|
|
270
|
+
// skipped below and then reverting anyway on this same call.
|
|
271
|
+
hubTotalAssets = IHub(hub).totalAssets();
|
|
272
|
+
|
|
273
|
+
address[] memory queue = IHub(hub).outerDepositQueue();
|
|
274
|
+
uint256 len = queue.length;
|
|
275
|
+
|
|
276
|
+
address[] memory groupBuffer = new address[](len);
|
|
277
|
+
HubCapacityMath.GroupInput[] memory inputBuffer = new HubCapacityMath.GroupInput[](len);
|
|
278
|
+
uint256 count;
|
|
279
|
+
|
|
280
|
+
for (uint256 i; i < len; ++i) {
|
|
281
|
+
address yieldGroup = queue[i];
|
|
282
|
+
IHub.YieldGroupConfig memory cfg = IHub(hub).yieldGroupConfig(yieldGroup);
|
|
283
|
+
if (!cfg.registered || cfg.paused) continue;
|
|
284
|
+
|
|
285
|
+
uint256 balance = IYieldGroupBase(yieldGroup).totalAssets();
|
|
286
|
+
|
|
287
|
+
uint256 venueRoom;
|
|
288
|
+
try IYieldGroupBase(yieldGroup).maxDeposit() returns (uint256 v) {
|
|
289
|
+
venueRoom = v;
|
|
290
|
+
} catch {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
groupBuffer[count] = yieldGroup;
|
|
295
|
+
inputBuffer[count] = HubCapacityMath.GroupInput({
|
|
296
|
+
balance: balance,
|
|
297
|
+
venueRoom: venueRoom,
|
|
298
|
+
absoluteCap: cfg.absoluteCap,
|
|
299
|
+
percentageCapBps: cfg.percentageCapBps
|
|
300
|
+
});
|
|
301
|
+
++count;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
groups = new address[](count);
|
|
305
|
+
inputs = new HubCapacityMath.GroupInput[](count);
|
|
306
|
+
for (uint256 i; i < count; ++i) {
|
|
307
|
+
groups[i] = groupBuffer[i];
|
|
308
|
+
inputs[i] = inputBuffer[i];
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"address": "
|
|
3
|
-
"block":
|
|
2
|
+
"address": "0xaa9D52758890997D91950E595886FF9CDEca81ae",
|
|
3
|
+
"block": 123325056,
|
|
4
4
|
"chainId": 56,
|
|
5
5
|
"contract": "AdapterCentrifuge",
|
|
6
6
|
"abi": [
|
|
@@ -295,6 +295,25 @@
|
|
|
295
295
|
"outputs": [],
|
|
296
296
|
"stateMutability": "nonpayable"
|
|
297
297
|
},
|
|
298
|
+
{
|
|
299
|
+
"type": "function",
|
|
300
|
+
"name": "resourceName",
|
|
301
|
+
"inputs": [
|
|
302
|
+
{
|
|
303
|
+
"name": "resource",
|
|
304
|
+
"type": "address",
|
|
305
|
+
"internalType": "address"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"outputs": [
|
|
309
|
+
{
|
|
310
|
+
"name": "",
|
|
311
|
+
"type": "string",
|
|
312
|
+
"internalType": "string"
|
|
313
|
+
}
|
|
314
|
+
],
|
|
315
|
+
"stateMutability": "view"
|
|
316
|
+
},
|
|
298
317
|
{
|
|
299
318
|
"type": "function",
|
|
300
319
|
"name": "spotAPYBps",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"address": "
|
|
3
|
-
"block":
|
|
2
|
+
"address": "0xa061cC2F62BDa2D6bA53Fb98847aD9822DA085dd",
|
|
3
|
+
"block": 123325056,
|
|
4
4
|
"chainId": 56,
|
|
5
5
|
"contract": "AdapterCoreV1",
|
|
6
6
|
"abi": [
|
|
@@ -158,6 +158,25 @@
|
|
|
158
158
|
],
|
|
159
159
|
"stateMutability": "view"
|
|
160
160
|
},
|
|
161
|
+
{
|
|
162
|
+
"type": "function",
|
|
163
|
+
"name": "resourceName",
|
|
164
|
+
"inputs": [
|
|
165
|
+
{
|
|
166
|
+
"name": "resource",
|
|
167
|
+
"type": "address",
|
|
168
|
+
"internalType": "address"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"outputs": [
|
|
172
|
+
{
|
|
173
|
+
"name": "",
|
|
174
|
+
"type": "string",
|
|
175
|
+
"internalType": "string"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"stateMutability": "view"
|
|
179
|
+
},
|
|
161
180
|
{
|
|
162
181
|
"type": "function",
|
|
163
182
|
"name": "spotAPYBps",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"address": "
|
|
3
|
-
"block":
|
|
2
|
+
"address": "0x1824caA965Ac05ae5C9C2819e045337e2cF5657c",
|
|
3
|
+
"block": 123325056,
|
|
4
4
|
"chainId": 56,
|
|
5
5
|
"contract": "AdapterFRV",
|
|
6
6
|
"abi": [
|
|
@@ -132,6 +132,25 @@
|
|
|
132
132
|
],
|
|
133
133
|
"stateMutability": "view"
|
|
134
134
|
},
|
|
135
|
+
{
|
|
136
|
+
"type": "function",
|
|
137
|
+
"name": "resourceName",
|
|
138
|
+
"inputs": [
|
|
139
|
+
{
|
|
140
|
+
"name": "resource",
|
|
141
|
+
"type": "address",
|
|
142
|
+
"internalType": "address"
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"outputs": [
|
|
146
|
+
{
|
|
147
|
+
"name": "",
|
|
148
|
+
"type": "string",
|
|
149
|
+
"internalType": "string"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"stateMutability": "view"
|
|
153
|
+
},
|
|
135
154
|
{
|
|
136
155
|
"type": "function",
|
|
137
156
|
"name": "spotAPYBps",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"address": "
|
|
3
|
-
"block":
|
|
2
|
+
"address": "0x9a1a7F6aebA4a1A3e85Ae1Dba90a7A2A52803404",
|
|
3
|
+
"block": 123325056,
|
|
4
4
|
"chainId": 56,
|
|
5
5
|
"contract": "AdapterFlux",
|
|
6
6
|
"abi": [
|
|
@@ -151,6 +151,25 @@
|
|
|
151
151
|
],
|
|
152
152
|
"stateMutability": "view"
|
|
153
153
|
},
|
|
154
|
+
{
|
|
155
|
+
"type": "function",
|
|
156
|
+
"name": "resourceName",
|
|
157
|
+
"inputs": [
|
|
158
|
+
{
|
|
159
|
+
"name": "resource",
|
|
160
|
+
"type": "address",
|
|
161
|
+
"internalType": "address"
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
"outputs": [
|
|
165
|
+
{
|
|
166
|
+
"name": "",
|
|
167
|
+
"type": "string",
|
|
168
|
+
"internalType": "string"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"stateMutability": "view"
|
|
172
|
+
},
|
|
154
173
|
{
|
|
155
174
|
"type": "function",
|
|
156
175
|
"name": "spotAPYBps",
|