protoscan 0.1.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.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2648 -0
- package/package.json +45 -0
- package/protoscan.config.json +20 -0
- package/src/chains.ts +38 -0
- package/src/config.ts +36 -0
- package/src/diff.ts +113 -0
- package/src/index.ts +289 -0
- package/src/protocols/common.ts +66 -0
- package/src/protocols/index.ts +2 -0
- package/src/protocols/proxy.ts +50 -0
- package/src/registry/aave-v3.ts +242 -0
- package/src/registry/compound-v3.ts +238 -0
- package/src/registry/eigenlayer.ts +190 -0
- package/src/registry/index.ts +38 -0
- package/src/registry/lido.ts +557 -0
- package/src/registry/maker.ts +176 -0
- package/src/registry/morpho-blue.ts +347 -0
- package/src/registry/pendle.ts +120 -0
- package/src/registry/schema.ts +40 -0
- package/src/registry/uniswap-v3.ts +198 -0
- package/src/scanner.ts +181 -0
- package/src/snapshot.ts +70 -0
- package/src/types.ts +67 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { parseAbi } from 'viem';
|
|
2
|
+
import type { ProtocolDef } from './schema.js';
|
|
3
|
+
|
|
4
|
+
const vatAbi = parseAbi([
|
|
5
|
+
'function Line() view returns (uint256)',
|
|
6
|
+
'function live() view returns (uint256)',
|
|
7
|
+
'function debt() view returns (uint256)',
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
const jugAbi = parseAbi([
|
|
11
|
+
'function base() view returns (uint256)',
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
const potAbi = parseAbi([
|
|
15
|
+
'function dsr() view returns (uint256)',
|
|
16
|
+
'function chi() view returns (uint256)',
|
|
17
|
+
'function Pie() view returns (uint256)',
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const dogAbi = parseAbi([
|
|
21
|
+
'function live() view returns (uint256)',
|
|
22
|
+
'function Hole() view returns (uint256)',
|
|
23
|
+
'function Dirt() view returns (uint256)',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const pauseAbi = parseAbi([
|
|
27
|
+
'function owner() view returns (address)',
|
|
28
|
+
'function authority() view returns (address)',
|
|
29
|
+
'function delay() view returns (uint256)',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const ownerAbi = parseAbi([
|
|
33
|
+
'function owner() view returns (address)',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export const maker: ProtocolDef = {
|
|
37
|
+
id: 'maker',
|
|
38
|
+
name: 'Maker (Sky)',
|
|
39
|
+
version: 'MCD',
|
|
40
|
+
website: 'https://makerdao.com',
|
|
41
|
+
description: 'Multi-collateral DAI stablecoin system',
|
|
42
|
+
|
|
43
|
+
contracts: {
|
|
44
|
+
MCD_VAT: { name: 'Vat', role: 'Core vault engine — tracks all debt and collateral', type: 'raw' },
|
|
45
|
+
MCD_JUG: { name: 'Jug', role: 'Stability fee accumulator', type: 'raw' },
|
|
46
|
+
MCD_POT: { name: 'Pot', role: 'DAI Savings Rate module', type: 'raw' },
|
|
47
|
+
MCD_DOG: { name: 'Dog', role: 'Liquidation engine', type: 'raw' },
|
|
48
|
+
MCD_SPOT: { name: 'Spotter', role: 'Oracle and liquidation ratio manager', type: 'raw' },
|
|
49
|
+
MCD_PAUSE: { name: 'DSPause', role: 'Governance timelock', type: 'raw' },
|
|
50
|
+
MCD_ADM: { name: 'DSChief', role: 'Governance voting contract', type: 'raw' },
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
deployments: {
|
|
54
|
+
ethereum: {
|
|
55
|
+
MCD_VAT: '0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B',
|
|
56
|
+
MCD_JUG: '0x19c0976f590D67707E62397C87829d896Dc0f1F1',
|
|
57
|
+
MCD_POT: '0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7',
|
|
58
|
+
MCD_DOG: '0x135954d155898D42C90D2a57824C690e0c7BEf1B',
|
|
59
|
+
MCD_SPOT: '0x65C79fcB50Ca1594B025960e539eD7A9a6D434A3',
|
|
60
|
+
MCD_PAUSE: '0xbE286431454714F511008713973d3B053A2d38f3',
|
|
61
|
+
MCD_ADM: '0x0a3f6849f78076aefaDf113F5BED87720274dDC0',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
params: [
|
|
66
|
+
{
|
|
67
|
+
name: 'globalDebtCeiling',
|
|
68
|
+
description: 'Global debt ceiling (Line) — max DAI that can be minted',
|
|
69
|
+
contract: 'MCD_VAT',
|
|
70
|
+
functionName: 'Line',
|
|
71
|
+
abi: vatAbi,
|
|
72
|
+
decode: 'ray',
|
|
73
|
+
category: 'risk',
|
|
74
|
+
severity: 'critical',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'totalDebt',
|
|
78
|
+
description: 'Total system debt',
|
|
79
|
+
contract: 'MCD_VAT',
|
|
80
|
+
functionName: 'debt',
|
|
81
|
+
abi: vatAbi,
|
|
82
|
+
decode: 'ray',
|
|
83
|
+
category: 'state',
|
|
84
|
+
severity: 'info',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'vatLive',
|
|
88
|
+
description: 'Vat live status (1=live, 0=caged/emergency shutdown)',
|
|
89
|
+
contract: 'MCD_VAT',
|
|
90
|
+
functionName: 'live',
|
|
91
|
+
abi: vatAbi,
|
|
92
|
+
decode: 'uint',
|
|
93
|
+
category: 'state',
|
|
94
|
+
severity: 'critical',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'baseRate',
|
|
98
|
+
description: 'Base stability fee rate applied to all vaults',
|
|
99
|
+
contract: 'MCD_JUG',
|
|
100
|
+
functionName: 'base',
|
|
101
|
+
abi: jugAbi,
|
|
102
|
+
decode: 'ray',
|
|
103
|
+
category: 'rate',
|
|
104
|
+
severity: 'warning',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'dsr',
|
|
108
|
+
description: 'DAI Savings Rate — per-second accumulation rate',
|
|
109
|
+
contract: 'MCD_POT',
|
|
110
|
+
functionName: 'dsr',
|
|
111
|
+
abi: potAbi,
|
|
112
|
+
decode: 'ray',
|
|
113
|
+
category: 'rate',
|
|
114
|
+
severity: 'warning',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'dsrTotalDeposits',
|
|
118
|
+
description: 'Total DAI deposited in DSR (Pie)',
|
|
119
|
+
contract: 'MCD_POT',
|
|
120
|
+
functionName: 'Pie',
|
|
121
|
+
abi: potAbi,
|
|
122
|
+
decode: 'wad',
|
|
123
|
+
category: 'state',
|
|
124
|
+
severity: 'info',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'dogLive',
|
|
128
|
+
description: 'Liquidation engine live status',
|
|
129
|
+
contract: 'MCD_DOG',
|
|
130
|
+
functionName: 'live',
|
|
131
|
+
abi: dogAbi,
|
|
132
|
+
decode: 'uint',
|
|
133
|
+
category: 'state',
|
|
134
|
+
severity: 'critical',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'globalLiquidationLimit',
|
|
138
|
+
description: 'Max DAI needed to cover all active auctions (Hole)',
|
|
139
|
+
contract: 'MCD_DOG',
|
|
140
|
+
functionName: 'Hole',
|
|
141
|
+
abi: dogAbi,
|
|
142
|
+
decode: 'ray',
|
|
143
|
+
category: 'risk',
|
|
144
|
+
severity: 'warning',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'timelockDelay',
|
|
148
|
+
description: 'Governance timelock delay in seconds',
|
|
149
|
+
contract: 'MCD_PAUSE',
|
|
150
|
+
functionName: 'delay',
|
|
151
|
+
abi: pauseAbi,
|
|
152
|
+
decode: 'uint',
|
|
153
|
+
category: 'config',
|
|
154
|
+
severity: 'critical',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
|
|
158
|
+
access: [
|
|
159
|
+
{
|
|
160
|
+
role: 'Pause Owner',
|
|
161
|
+
description: 'Owner of governance timelock — can schedule spells',
|
|
162
|
+
contract: 'MCD_PAUSE',
|
|
163
|
+
functionName: 'owner',
|
|
164
|
+
abi: pauseAbi,
|
|
165
|
+
severity: 'critical',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
role: 'Pause Authority',
|
|
169
|
+
description: 'Authority contract — typically DSChief governance',
|
|
170
|
+
contract: 'MCD_PAUSE',
|
|
171
|
+
functionName: 'authority',
|
|
172
|
+
abi: pauseAbi,
|
|
173
|
+
severity: 'critical',
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { parseAbi } from 'viem';
|
|
2
|
+
import type { ProtocolDef } from './schema.js';
|
|
3
|
+
|
|
4
|
+
const morphoAbi = parseAbi([
|
|
5
|
+
'function owner() view returns (address)',
|
|
6
|
+
'function feeRecipient() view returns (address)',
|
|
7
|
+
'function isIrmEnabled(address irm) view returns (bool)',
|
|
8
|
+
'function isLltvEnabled(uint256 lltv) view returns (bool)',
|
|
9
|
+
'function isAuthorized(address authorizer, address authorized) view returns (bool)',
|
|
10
|
+
'function nonce(address authorizer) view returns (uint256)',
|
|
11
|
+
'function market(bytes32 id) view returns ((uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee))',
|
|
12
|
+
'function idToMarketParams(bytes32 id) view returns ((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv))',
|
|
13
|
+
'function position(bytes32 id, address user) view returns ((uint256 supplyShares, uint128 borrowShares, uint128 collateral))',
|
|
14
|
+
'function DOMAIN_SEPARATOR() view returns (bytes32)',
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
const irmAbi = parseAbi([
|
|
18
|
+
'function MORPHO() view returns (address)',
|
|
19
|
+
'function rateAtTarget(bytes32 id) view returns (int256)',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
const metaMorphoFactoryAbi = parseAbi([
|
|
23
|
+
'function isMetaMorpho(address target) view returns (bool)',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const publicAllocatorAbi = parseAbi([
|
|
27
|
+
'function admin(address vault) view returns (address)',
|
|
28
|
+
'function fee(address vault) view returns (uint256)',
|
|
29
|
+
'function accruedFee(address vault) view returns (uint256)',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const chainlinkOracleFactoryAbi = parseAbi([
|
|
33
|
+
'function isMorphoChainlinkOracleV2(address target) view returns (bool)',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
// MetaMorpho vault ABI (ERC-4626 + Morpho curation layer).
|
|
37
|
+
// Every vault is a permissionless instance deployed by MetaMorphoFactory /
|
|
38
|
+
// MetaMorphoFactoryV1_1 — there is no single canonical vault. FlagshipUsdcVault
|
|
39
|
+
// below (Steakhouse USDC) is tracked as a representative, high-TVL example.
|
|
40
|
+
const vaultAbi = parseAbi([
|
|
41
|
+
'function owner() view returns (address)',
|
|
42
|
+
'function curator() view returns (address)',
|
|
43
|
+
'function guardian() view returns (address)',
|
|
44
|
+
'function isAllocator(address target) view returns (bool)',
|
|
45
|
+
'function timelock() view returns (uint256)',
|
|
46
|
+
'function fee() view returns (uint96)',
|
|
47
|
+
'function feeRecipient() view returns (address)',
|
|
48
|
+
'function skimRecipient() view returns (address)',
|
|
49
|
+
'function asset() view returns (address)',
|
|
50
|
+
'function totalAssets() view returns (uint256)',
|
|
51
|
+
'function supplyQueueLength() view returns (uint256)',
|
|
52
|
+
'function withdrawQueueLength() view returns (uint256)',
|
|
53
|
+
'function config(bytes32 id) view returns ((uint184 cap, bool enabled, uint64 removableAt))',
|
|
54
|
+
'function DECIMALS_OFFSET() view returns (uint8)',
|
|
55
|
+
'function MORPHO() view returns (address)',
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
export const morphoBlue: ProtocolDef = {
|
|
59
|
+
id: 'morpho-blue',
|
|
60
|
+
name: 'Morpho Blue',
|
|
61
|
+
version: '1.0',
|
|
62
|
+
website: 'https://morpho.org',
|
|
63
|
+
description: 'Immutable, oracle-agnostic isolated lending primitive with a permissionless MetaMorpho vault curation layer',
|
|
64
|
+
|
|
65
|
+
contracts: {
|
|
66
|
+
Morpho: { name: 'Morpho', role: 'Core immutable lending singleton — isolated markets, no upgradeability', type: 'raw' },
|
|
67
|
+
AdaptiveCurveIrm: { name: 'AdaptiveCurveIrm', role: 'Default interest rate model targeting ~90% utilization', type: 'raw' },
|
|
68
|
+
MetaMorphoFactory: { name: 'MetaMorpho Factory (v1.0)', role: 'Original factory deploying MetaMorpho vault instances', type: 'raw' },
|
|
69
|
+
MetaMorphoFactoryV1_1: { name: 'MetaMorpho Factory v1.1', role: 'Current factory deploying MetaMorphoV1_1 vault instances', type: 'raw' },
|
|
70
|
+
PublicAllocator: { name: 'Public Allocator', role: 'Permissionless reallocation of vault liquidity within curator-set flow caps', type: 'raw' },
|
|
71
|
+
ChainlinkOracleFactory: { name: 'MorphoChainlinkOracleV2 Factory', role: 'Deploys Chainlink-backed market oracle adaptors', type: 'raw' },
|
|
72
|
+
BundlerV2: { name: 'Bundler V2', role: 'Multicall router for atomic supply/borrow/flashloan bundles', type: 'raw' },
|
|
73
|
+
Bundler3: { name: 'Bundler3', role: 'Successor multicall router with generalized adapters', type: 'raw' },
|
|
74
|
+
FlagshipUsdcVault: { name: 'Steakhouse USDC Vault', role: 'Representative MetaMorpho vault instance (flagship USDC market)', type: 'raw' },
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
deployments: {
|
|
78
|
+
ethereum: {
|
|
79
|
+
Morpho: '0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb',
|
|
80
|
+
AdaptiveCurveIrm: '0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC',
|
|
81
|
+
MetaMorphoFactory: '0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101',
|
|
82
|
+
MetaMorphoFactoryV1_1: '0x1897A8997241C1cD4bD0698647e4EB7213535c24',
|
|
83
|
+
PublicAllocator: '0xfd32fA2ca22c76dD6E550706Ad913FC6CE91c75D',
|
|
84
|
+
ChainlinkOracleFactory: '0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766',
|
|
85
|
+
BundlerV2: '0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077',
|
|
86
|
+
Bundler3: '0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245',
|
|
87
|
+
FlagshipUsdcVault: '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB',
|
|
88
|
+
},
|
|
89
|
+
base: {
|
|
90
|
+
Morpho: '0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb',
|
|
91
|
+
AdaptiveCurveIrm: '0x46415998764C29aB2a25CbeA6254146D50D22687',
|
|
92
|
+
MetaMorphoFactoryV1_1: '0xFf62A7c278C62eD665133147129245053Bbf5918',
|
|
93
|
+
PublicAllocator: '0xA090dD1a701408Df1d4d0B85b716c87565f90467',
|
|
94
|
+
ChainlinkOracleFactory: '0x2DC205F24BCb6B311E5cdf0745B0741648Aebd3d',
|
|
95
|
+
BundlerV2: '0x23055618898e202386e6c13955a58D3C68200BFB',
|
|
96
|
+
Bundler3: '0x6BFd8137e702540E7A42B74178A4a49Ba43920C4',
|
|
97
|
+
FlagshipUsdcVault: '0xCBeeF01994E24a60f7DCB8De98e75AD8BD4Ad60d',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
params: [
|
|
102
|
+
{
|
|
103
|
+
name: 'morphoOwner',
|
|
104
|
+
description: 'Morpho core owner — can enable new IRMs/LLTVs and set the fee recipient, but cannot touch existing market params (immutable by design)',
|
|
105
|
+
contract: 'Morpho',
|
|
106
|
+
functionName: 'owner',
|
|
107
|
+
abi: morphoAbi,
|
|
108
|
+
decode: 'address',
|
|
109
|
+
category: 'access',
|
|
110
|
+
severity: 'critical',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'morphoFeeRecipient',
|
|
114
|
+
description: 'Recipient of protocol fees accrued across all markets',
|
|
115
|
+
contract: 'Morpho',
|
|
116
|
+
functionName: 'feeRecipient',
|
|
117
|
+
abi: morphoAbi,
|
|
118
|
+
decode: 'address',
|
|
119
|
+
category: 'config',
|
|
120
|
+
severity: 'warning',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'adaptiveCurveIrmEnabled',
|
|
124
|
+
description: 'Whether AdaptiveCurveIrm is whitelisted as an approved IRM on Ethereum mainnet',
|
|
125
|
+
contract: 'Morpho',
|
|
126
|
+
functionName: 'isIrmEnabled',
|
|
127
|
+
args: ['0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'],
|
|
128
|
+
abi: morphoAbi,
|
|
129
|
+
decode: 'bool',
|
|
130
|
+
category: 'config',
|
|
131
|
+
severity: 'info',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'lltv86PercentEnabled',
|
|
135
|
+
description: 'Whether the 86% LLTV tier is whitelisted (one of the standard risk tiers)',
|
|
136
|
+
contract: 'Morpho',
|
|
137
|
+
functionName: 'isLltvEnabled',
|
|
138
|
+
args: [860000000000000000n],
|
|
139
|
+
abi: morphoAbi,
|
|
140
|
+
decode: 'bool',
|
|
141
|
+
category: 'risk',
|
|
142
|
+
severity: 'info',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'irmMorphoRef',
|
|
146
|
+
description: 'Morpho core address the AdaptiveCurveIrm is bound to — must match the deployed Morpho singleton',
|
|
147
|
+
contract: 'AdaptiveCurveIrm',
|
|
148
|
+
functionName: 'MORPHO',
|
|
149
|
+
abi: irmAbi,
|
|
150
|
+
decode: 'address',
|
|
151
|
+
category: 'config',
|
|
152
|
+
severity: 'info',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'factoryRecognizesFlagshipVault',
|
|
156
|
+
description: 'Confirms the flagship USDC vault (deployed pre-v1.1) was created by the original MetaMorphoFactory — sanity check against spoofed vault UIs',
|
|
157
|
+
contract: 'MetaMorphoFactory',
|
|
158
|
+
functionName: 'isMetaMorpho',
|
|
159
|
+
args: ['0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB'],
|
|
160
|
+
abi: metaMorphoFactoryAbi,
|
|
161
|
+
decode: 'bool',
|
|
162
|
+
category: 'config',
|
|
163
|
+
severity: 'info',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'cbbtcUsdcOracleIsFactoryDeployed',
|
|
167
|
+
description: 'Confirms the oracle used by the flagship vault\'s first supply-queue market (cbBTC/USDC, 86% LLTV) was deployed by the canonical MorphoChainlinkOracleV2Factory — sanity check against a spoofed/malicious oracle',
|
|
168
|
+
contract: 'ChainlinkOracleFactory',
|
|
169
|
+
functionName: 'isMorphoChainlinkOracleV2',
|
|
170
|
+
args: ['0xA6D6950c9F177F1De7f7757FB33539e3Ec60182a'],
|
|
171
|
+
abi: chainlinkOracleFactoryAbi,
|
|
172
|
+
decode: 'bool',
|
|
173
|
+
category: 'risk',
|
|
174
|
+
severity: 'info',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: 'publicAllocatorAdmin',
|
|
178
|
+
description: 'Address allowed to set flow caps for the flagship vault on the Public Allocator — can trigger instant reallocation within curator-approved caps',
|
|
179
|
+
contract: 'PublicAllocator',
|
|
180
|
+
functionName: 'admin',
|
|
181
|
+
args: ['0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB'],
|
|
182
|
+
abi: publicAllocatorAbi,
|
|
183
|
+
decode: 'address',
|
|
184
|
+
category: 'access',
|
|
185
|
+
severity: 'warning',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'publicAllocatorFee',
|
|
189
|
+
description: 'Fee (wei) charged by the Public Allocator for reallocating the flagship vault',
|
|
190
|
+
contract: 'PublicAllocator',
|
|
191
|
+
functionName: 'fee',
|
|
192
|
+
args: ['0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB'],
|
|
193
|
+
abi: publicAllocatorAbi,
|
|
194
|
+
decode: 'uint',
|
|
195
|
+
category: 'config',
|
|
196
|
+
severity: 'info',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'vaultOwner',
|
|
200
|
+
description: 'Vault owner — can set curator, guardian, timelock and allocators; ultimate control over vault configuration',
|
|
201
|
+
contract: 'FlagshipUsdcVault',
|
|
202
|
+
functionName: 'owner',
|
|
203
|
+
abi: vaultAbi,
|
|
204
|
+
decode: 'address',
|
|
205
|
+
category: 'access',
|
|
206
|
+
severity: 'critical',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: 'vaultCurator',
|
|
210
|
+
description: 'Curator — whitelists markets and sets/lowers supply caps for the vault',
|
|
211
|
+
contract: 'FlagshipUsdcVault',
|
|
212
|
+
functionName: 'curator',
|
|
213
|
+
abi: vaultAbi,
|
|
214
|
+
decode: 'address',
|
|
215
|
+
category: 'access',
|
|
216
|
+
severity: 'critical',
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: 'vaultGuardian',
|
|
220
|
+
description: 'Guardian — can revoke pending timelocked changes (cap increases, guardian/timelock changes, market removals)',
|
|
221
|
+
contract: 'FlagshipUsdcVault',
|
|
222
|
+
functionName: 'guardian',
|
|
223
|
+
abi: vaultAbi,
|
|
224
|
+
decode: 'address',
|
|
225
|
+
category: 'access',
|
|
226
|
+
severity: 'critical',
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
name: 'vaultTimelock',
|
|
230
|
+
description: 'Timelock delay (seconds) applied to risk-sensitive vault changes',
|
|
231
|
+
contract: 'FlagshipUsdcVault',
|
|
232
|
+
functionName: 'timelock',
|
|
233
|
+
abi: vaultAbi,
|
|
234
|
+
decode: 'uint',
|
|
235
|
+
category: 'config',
|
|
236
|
+
severity: 'warning',
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: 'vaultFee',
|
|
240
|
+
description: 'Performance fee taken from vault yield (WAD-scaled fraction)',
|
|
241
|
+
contract: 'FlagshipUsdcVault',
|
|
242
|
+
functionName: 'fee',
|
|
243
|
+
abi: vaultAbi,
|
|
244
|
+
decode: 'wad',
|
|
245
|
+
category: 'config',
|
|
246
|
+
severity: 'warning',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'vaultFeeRecipient',
|
|
250
|
+
description: 'Recipient of the vault performance fee',
|
|
251
|
+
contract: 'FlagshipUsdcVault',
|
|
252
|
+
functionName: 'feeRecipient',
|
|
253
|
+
abi: vaultAbi,
|
|
254
|
+
decode: 'address',
|
|
255
|
+
category: 'config',
|
|
256
|
+
severity: 'warning',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: 'vaultSkimRecipient',
|
|
260
|
+
description: 'Receives non-asset token dust skimmed from the vault',
|
|
261
|
+
contract: 'FlagshipUsdcVault',
|
|
262
|
+
functionName: 'skimRecipient',
|
|
263
|
+
abi: vaultAbi,
|
|
264
|
+
decode: 'address',
|
|
265
|
+
category: 'config',
|
|
266
|
+
severity: 'info',
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: 'vaultAsset',
|
|
270
|
+
description: 'Underlying ERC-4626 asset held by the vault',
|
|
271
|
+
contract: 'FlagshipUsdcVault',
|
|
272
|
+
functionName: 'asset',
|
|
273
|
+
abi: vaultAbi,
|
|
274
|
+
decode: 'address',
|
|
275
|
+
category: 'config',
|
|
276
|
+
severity: 'info',
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'vaultTotalAssets',
|
|
280
|
+
description: 'Total assets under management in the vault',
|
|
281
|
+
contract: 'FlagshipUsdcVault',
|
|
282
|
+
functionName: 'totalAssets',
|
|
283
|
+
abi: vaultAbi,
|
|
284
|
+
decode: 'uint',
|
|
285
|
+
category: 'state',
|
|
286
|
+
severity: 'info',
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: 'vaultSupplyQueueLength',
|
|
290
|
+
description: 'Number of markets in the vault supply queue',
|
|
291
|
+
contract: 'FlagshipUsdcVault',
|
|
292
|
+
functionName: 'supplyQueueLength',
|
|
293
|
+
abi: vaultAbi,
|
|
294
|
+
decode: 'uint',
|
|
295
|
+
category: 'state',
|
|
296
|
+
severity: 'info',
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: 'vaultWithdrawQueueLength',
|
|
300
|
+
description: 'Number of markets in the vault withdraw queue',
|
|
301
|
+
contract: 'FlagshipUsdcVault',
|
|
302
|
+
functionName: 'withdrawQueueLength',
|
|
303
|
+
abi: vaultAbi,
|
|
304
|
+
decode: 'uint',
|
|
305
|
+
category: 'state',
|
|
306
|
+
severity: 'info',
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
|
|
310
|
+
access: [
|
|
311
|
+
{
|
|
312
|
+
role: 'Morpho Core Owner',
|
|
313
|
+
description: 'Can enable new IRMs/LLTVs and change the fee recipient. Cannot alter existing market params or seize funds — Morpho Blue markets are immutable once created',
|
|
314
|
+
contract: 'Morpho',
|
|
315
|
+
functionName: 'owner',
|
|
316
|
+
abi: morphoAbi,
|
|
317
|
+
severity: 'critical',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
role: 'Vault Owner',
|
|
321
|
+
description: 'Full control over a MetaMorpho vault — sets curator, guardian, timelock, allocators, fee recipient',
|
|
322
|
+
contract: 'FlagshipUsdcVault',
|
|
323
|
+
functionName: 'owner',
|
|
324
|
+
abi: vaultAbi,
|
|
325
|
+
severity: 'critical',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
role: 'Vault Curator',
|
|
329
|
+
description: 'Decides which markets the vault can allocate to and the supply cap per market — primary risk-management role',
|
|
330
|
+
contract: 'FlagshipUsdcVault',
|
|
331
|
+
functionName: 'curator',
|
|
332
|
+
abi: vaultAbi,
|
|
333
|
+
severity: 'critical',
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
role: 'Vault Guardian',
|
|
337
|
+
description: 'Can revoke pending timelocked changes (malicious cap increases, curator/guardian/timelock swaps) before they execute',
|
|
338
|
+
contract: 'FlagshipUsdcVault',
|
|
339
|
+
functionName: 'guardian',
|
|
340
|
+
abi: vaultAbi,
|
|
341
|
+
severity: 'critical',
|
|
342
|
+
},
|
|
343
|
+
// Note: Public Allocator's admin/fee are per-vault (take an `address vault`
|
|
344
|
+
// argument), so they're only tracked as `params` (which support `args`) —
|
|
345
|
+
// `access` entries are always read with zero arguments by the scanner.
|
|
346
|
+
],
|
|
347
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { parseAbi } from 'viem';
|
|
2
|
+
import type { ProtocolDef } from './schema.js';
|
|
3
|
+
|
|
4
|
+
const marketFactoryAbi = parseAbi([
|
|
5
|
+
'function owner() view returns (address)',
|
|
6
|
+
'function pendingOwner() view returns (address)',
|
|
7
|
+
'function treasury() view returns (address)',
|
|
8
|
+
'function reserveFeePercent() view returns (uint256)',
|
|
9
|
+
'function vePendle() view returns (address)',
|
|
10
|
+
'function interestFeeRate() view returns (uint256)',
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const vePendleAbi = parseAbi([
|
|
14
|
+
'function totalSupplyStored() view returns (uint128)',
|
|
15
|
+
'function lastSlopeChangeAppliedAt() view returns (uint128)',
|
|
16
|
+
'function pendle() view returns (address)',
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const routerAbi = parseAbi([
|
|
20
|
+
'function owner() view returns (address)',
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
export const pendle: ProtocolDef = {
|
|
24
|
+
id: 'pendle',
|
|
25
|
+
name: 'Pendle',
|
|
26
|
+
version: '2.0',
|
|
27
|
+
website: 'https://pendle.finance',
|
|
28
|
+
description: 'Yield trading protocol — tokenize and trade future yield',
|
|
29
|
+
|
|
30
|
+
contracts: {
|
|
31
|
+
PendleMarketFactory: { name: 'MarketFactory', role: 'Creates PT/YT markets', type: 'raw' },
|
|
32
|
+
vePENDLE: { name: 'vePENDLE', role: 'Vote-escrowed PENDLE for governance', type: 'raw' },
|
|
33
|
+
PendleRouter: { name: 'Router', role: 'Main swap/liquidity router', type: 'raw' },
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
deployments: {
|
|
37
|
+
ethereum: {
|
|
38
|
+
PendleMarketFactory: '0x1A6fCc85557BC4fB7B534ed835a03EF056c22E23',
|
|
39
|
+
vePENDLE: '0x4f30A9D41B80ecC5B94306AB4364951AE3170210',
|
|
40
|
+
PendleRouter: '0x888888888889758F76e7103c6CbF23ABbF58F946',
|
|
41
|
+
},
|
|
42
|
+
arbitrum: {
|
|
43
|
+
PendleMarketFactory: '0x2FCb47B58350cD377f94d3a40c938fB1CF7e5Dd5',
|
|
44
|
+
vePENDLE: '0x3209E9412cca80B18338f2a56ADA59c484c39644',
|
|
45
|
+
PendleRouter: '0x888888888889758F76e7103c6CbF23ABbF58F946',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
params: [
|
|
50
|
+
{
|
|
51
|
+
name: 'treasury',
|
|
52
|
+
description: 'Protocol treasury address — receives fees',
|
|
53
|
+
contract: 'PendleMarketFactory',
|
|
54
|
+
functionName: 'treasury',
|
|
55
|
+
abi: marketFactoryAbi,
|
|
56
|
+
decode: 'address',
|
|
57
|
+
category: 'config',
|
|
58
|
+
severity: 'critical',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'reserveFeePercent',
|
|
62
|
+
description: 'Fee percentage taken from yield as protocol revenue',
|
|
63
|
+
contract: 'PendleMarketFactory',
|
|
64
|
+
functionName: 'reserveFeePercent',
|
|
65
|
+
abi: marketFactoryAbi,
|
|
66
|
+
decode: 'uint',
|
|
67
|
+
category: 'config',
|
|
68
|
+
severity: 'warning',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'interestFeeRate',
|
|
72
|
+
description: 'Interest fee rate applied to markets',
|
|
73
|
+
contract: 'PendleMarketFactory',
|
|
74
|
+
functionName: 'interestFeeRate',
|
|
75
|
+
abi: marketFactoryAbi,
|
|
76
|
+
decode: 'uint',
|
|
77
|
+
category: 'rate',
|
|
78
|
+
severity: 'warning',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'vePendleTotalSupply',
|
|
82
|
+
description: 'Total vePENDLE supply (governance power)',
|
|
83
|
+
contract: 'vePENDLE',
|
|
84
|
+
functionName: 'totalSupplyStored',
|
|
85
|
+
abi: vePendleAbi,
|
|
86
|
+
decode: 'wad',
|
|
87
|
+
category: 'state',
|
|
88
|
+
severity: 'info',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'pendingOwner',
|
|
92
|
+
description: 'Pending ownership transfer target',
|
|
93
|
+
contract: 'PendleMarketFactory',
|
|
94
|
+
functionName: 'pendingOwner',
|
|
95
|
+
abi: marketFactoryAbi,
|
|
96
|
+
decode: 'address',
|
|
97
|
+
category: 'access',
|
|
98
|
+
severity: 'critical',
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
|
|
102
|
+
access: [
|
|
103
|
+
{
|
|
104
|
+
role: 'MarketFactory Owner',
|
|
105
|
+
description: 'Can create markets, set fees, set treasury',
|
|
106
|
+
contract: 'PendleMarketFactory',
|
|
107
|
+
functionName: 'owner',
|
|
108
|
+
abi: marketFactoryAbi,
|
|
109
|
+
severity: 'critical',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
role: 'Router Owner',
|
|
113
|
+
description: 'Can update router configuration',
|
|
114
|
+
contract: 'PendleRouter',
|
|
115
|
+
functionName: 'owner',
|
|
116
|
+
abi: routerAbi,
|
|
117
|
+
severity: 'critical',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Address, Abi } from 'viem';
|
|
2
|
+
|
|
3
|
+
export interface ParamDef {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
contract: string;
|
|
7
|
+
functionName: string;
|
|
8
|
+
abi: Abi;
|
|
9
|
+
args?: any[];
|
|
10
|
+
decode?: 'percent' | 'bps' | 'ray' | 'wad' | 'address' | 'bool' | 'uint' | 'string';
|
|
11
|
+
category: 'risk' | 'rate' | 'access' | 'config' | 'state';
|
|
12
|
+
severity: 'critical' | 'warning' | 'info';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ContractDef {
|
|
16
|
+
name: string;
|
|
17
|
+
role: string;
|
|
18
|
+
type: 'proxy' | 'raw' | 'multisig';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AccessDef {
|
|
22
|
+
role: string;
|
|
23
|
+
description: string;
|
|
24
|
+
contract: string;
|
|
25
|
+
functionName: string;
|
|
26
|
+
abi: Abi;
|
|
27
|
+
severity: 'critical' | 'warning';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ProtocolDef {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
version: string;
|
|
34
|
+
website: string;
|
|
35
|
+
description: string;
|
|
36
|
+
contracts: Record<string, ContractDef>;
|
|
37
|
+
deployments: Record<string, Record<string, Address>>;
|
|
38
|
+
params: ParamDef[];
|
|
39
|
+
access: AccessDef[];
|
|
40
|
+
}
|