Skip to content

Commit 38fa459

Browse files
committed
feat: allow list features
1 parent f66d7fd commit 38fa459

File tree

4 files changed

+232
-5
lines changed

4 files changed

+232
-5
lines changed

features/defi-wrapper/pool-info.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
import { callReadMethodSilent } from 'utils';
77
import { reportFreshWarning } from 'features';
88

9-
const STV_POOL_NAME = 'StvPool';
10-
const STV_STETH_POOL_NAME = 'StvStETHPool';
11-
const STV_STRATEGY_POOL_NAME = 'StvStrategyPool';
9+
export const STV_POOL_NAME = 'StvPool';
10+
export const STV_STETH_POOL_NAME = 'StvStETHPool';
11+
export const STV_STRATEGY_POOL_NAME = 'StvStrategyPool';
1212

1313
const getStvPoolInfo = async (address: Address) => {
1414
const contract = await getStvPoolContract(address);

programs/defi-wrapper/use-cases/wrapper-operations/read.ts

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
logResult,
99
formatBP,
1010
callReadMethodSilent,
11+
stringArrayToAddressArray,
1112
} from 'utils';
1213
import { getPoolInfo } from 'features/defi-wrapper/index.js';
1314
import { checkIsReportFresh } from 'features';
@@ -19,6 +20,7 @@ import {
1920
import { wrapperOperations } from './main.js';
2021
import { getDashboardContract, getStethContract } from 'contracts';
2122
import { bigIntMin } from 'utils/bigInt.js';
23+
import { getPublicClient } from 'providers';
2224

2325
const wrapperOperationsRead = wrapperOperations
2426
.command('read')
@@ -117,6 +119,67 @@ wrapperOperationsRead
117119
});
118120
});
119121

122+
wrapperOperationsRead
123+
.command('allow-list')
124+
.description('get full or partial allow list data')
125+
.argument('<address>', 'wrapper address', stringToAddress)
126+
.argument(
127+
'[addresses...]',
128+
'list of addresses to check, leave empty to get full allow list',
129+
stringArrayToAddressArray,
130+
[],
131+
)
132+
.action(async (poolAddress, addresses: Address[]) => {
133+
const pool = await getStvPoolContract(poolAddress);
134+
const publicClient = await getPublicClient();
135+
const isAllowListEnabled = await callReadMethodSilent({
136+
contract: pool,
137+
methodName: 'ALLOW_LIST_ENABLED',
138+
payload: [],
139+
});
140+
if (!isAllowListEnabled) {
141+
logInfo('Allow List is disabled for this pool');
142+
return;
143+
}
144+
145+
const allowListSize = await callReadMethodSilent({
146+
contract: pool,
147+
methodName: 'getAllowListSize',
148+
payload: [],
149+
});
150+
logInfo(`Allow List contains ${allowListSize} addresses:`);
151+
152+
if (addresses.length === 0) {
153+
const fullAllowList = await callReadMethodSilent({
154+
contract: pool,
155+
methodName: 'getAllowListAddresses',
156+
payload: [],
157+
});
158+
159+
logTable({ data: fullAllowList.map((addr) => [addr]) });
160+
} else {
161+
const result = await publicClient.multicall({
162+
contracts: addresses.map(
163+
(address) =>
164+
({
165+
address: pool.address,
166+
abi: pool.abi,
167+
functionName: 'isAllowListed',
168+
args: [address],
169+
}) as const,
170+
),
171+
allowFailure: false,
172+
});
173+
174+
logTable({
175+
data: result.map((isAllowed, index) => [
176+
addresses[index],
177+
isAllowed ? '✅ Allowed' : '❌ Not Allowed',
178+
]),
179+
});
180+
}
181+
});
182+
120183
wrapperOperationsRead
121184
.command('report-fresh')
122185
.description('check if report is fresh')
@@ -144,7 +207,7 @@ const finalizationBlocker = (amount: bigint) => {
144207
wrapperOperationsRead
145208
.command('withdrawal-status')
146209
.description('get status of withdrawal queue')
147-
.argument('<address>', 'wrapper address', stringToAddress)
210+
.argument('<address>', 'wrapper address', stringArrayToAddressArray)
148211
.action(async (address: Address) => {
149212
const pool = await getStvPoolContract(address);
150213
const withdrawalQueueAddress = await callReadMethodSilent({

programs/defi-wrapper/use-cases/wrapper-operations/write.ts

Lines changed: 158 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,26 @@ import {
88
confirmOperation,
99
submitReport,
1010
callWriteMethodWithReceipt,
11+
logError,
12+
logTable,
13+
callWriteMethodWithReceiptBatchCalls,
14+
stringArrayToAddressArray,
1115
} from 'utils';
1216
import { wrapperOperations } from './main.js';
1317
import { getWithdrawalQueueContract } from 'contracts/defi-wrapper/withdrawal-queue.js';
14-
import { formatEther, zeroAddress, type Address } from 'viem';
18+
import {
19+
encodeFunctionData,
20+
formatEther,
21+
fromHex,
22+
parseEventLogs,
23+
zeroAddress,
24+
type Address,
25+
} from 'viem';
1526
import { getDashboardContract, getVaultHubContract } from 'contracts';
1627
import { getStvPoolContract } from 'contracts/defi-wrapper/stv-pool.js';
1728
import { bigIntMin } from 'utils/bigInt.js';
29+
import { getStvStethPoolContract } from 'contracts/defi-wrapper/stv-steth-pool.js';
30+
import { STV_STETH_POOL_NAME, STV_STRATEGY_POOL_NAME } from 'features';
1831
export const wrapperOperationsWrite = wrapperOperations
1932
.command('write')
2033
.aliases(['w'])
@@ -191,3 +204,147 @@ wrapperOperationsWrite
191204
});
192205
},
193206
);
207+
208+
wrapperOperationsWrite
209+
.command('sync-vault-params')
210+
.description('sync vault params between vault & pool')
211+
.argument('<poolAddress>', 'pool address', stringToAddress)
212+
.action(async (address: Address) => {
213+
const pool = await getStvStethPoolContract(address);
214+
215+
const poolType = await callReadMethod({
216+
contract: pool,
217+
methodName: 'poolType',
218+
payload: [],
219+
});
220+
221+
const poolTypeName = fromHex(poolType, 'string').replace(/\W/g, '');
222+
223+
const isStvStethPool =
224+
poolTypeName === STV_STETH_POOL_NAME ||
225+
poolTypeName === STV_STRATEGY_POOL_NAME;
226+
227+
if (!isStvStethPool) {
228+
logError(
229+
`The pool at address ${address} is not an StvStEth or StvStrategy pool. This operation is only applicable to StvStEth and StvStrategy pools.`,
230+
);
231+
return;
232+
}
233+
234+
const { receipt } = await callWriteMethodWithReceipt({
235+
contract: pool,
236+
methodName: 'syncVaultParameters',
237+
payload: [],
238+
});
239+
240+
if (receipt?.logs) {
241+
const logs = parseEventLogs({
242+
abi: pool.abi,
243+
logs: receipt.logs,
244+
strict: true,
245+
});
246+
247+
const hadEffect = logs.find(
248+
(log) => log.eventName === 'VaultParametersUpdated',
249+
);
250+
251+
if (!hadEffect) {
252+
logInfo(
253+
'⚠️⚠️⚠️ Vault parameters are already in sync. No changes were made during your tx. ⚠️⚠️⚠️',
254+
);
255+
return;
256+
}
257+
}
258+
});
259+
260+
wrapperOperationsWrite
261+
.command('allow-list-add')
262+
.description('add addresses(divided by spaces) to allow list ')
263+
.argument('<poolAddress>', 'pool address', stringToAddress)
264+
.argument(
265+
'<addressToAdd...>',
266+
'1 or more addresses to add to allow list divided by spaces',
267+
stringArrayToAddressArray,
268+
[],
269+
)
270+
.action(async (address: Address, addressToAdd: Address[]) => {
271+
const pool = await getStvPoolContract(address);
272+
const isAllowListEnabled = await callReadMethod({
273+
contract: pool,
274+
methodName: 'ALLOW_LIST_ENABLED',
275+
payload: [],
276+
});
277+
278+
if (!isAllowListEnabled) {
279+
logError('Pool is not configured for using allow list.');
280+
return;
281+
}
282+
283+
logTable({
284+
data: addressToAdd.map((addr) => [addr]),
285+
params: { head: ['Addresses to be added to allow list:'] },
286+
});
287+
288+
const confirm = await confirmOperation(
289+
`Are you sure you want to add ${addressToAdd.length} addresses to the allow list of the pool at address: ${address}?`,
290+
);
291+
if (!confirm) return;
292+
293+
await callWriteMethodWithReceiptBatchCalls({
294+
calls: addressToAdd.map((addr) => ({
295+
to: pool.address,
296+
data: encodeFunctionData({
297+
abi: pool.abi,
298+
functionName: 'addToAllowList',
299+
args: [addr],
300+
}),
301+
value: 0n,
302+
})),
303+
});
304+
});
305+
306+
wrapperOperationsWrite
307+
.command('allow-list-remove')
308+
.description('remove addresses(divided by spaces) from allow list ')
309+
.argument('<poolAddress>', 'pool address', stringToAddress)
310+
.argument(
311+
'[addressesToRemove...]',
312+
'1 or more addresses to remove divided by spaces',
313+
stringArrayToAddressArray,
314+
[],
315+
)
316+
.action(async (address: Address, addressesToRemove: Address[]) => {
317+
const pool = await getStvPoolContract(address);
318+
const isAllowListEnabled = await callReadMethod({
319+
contract: pool,
320+
methodName: 'ALLOW_LIST_ENABLED',
321+
payload: [],
322+
});
323+
324+
if (!isAllowListEnabled) {
325+
logError('Pool is not configured for using allow list.');
326+
return;
327+
}
328+
329+
logTable({
330+
data: addressesToRemove.map((addr) => [addr]),
331+
params: { head: ['Addresses to be removed from allow list:'] },
332+
});
333+
334+
const confirm = await confirmOperation(
335+
`Are you sure you want to remove ${addressesToRemove.length} addresses from the allow list of the pool at address: ${address}?`,
336+
);
337+
if (!confirm) return;
338+
339+
await callWriteMethodWithReceiptBatchCalls({
340+
calls: addressesToRemove.map((addr) => ({
341+
to: pool.address,
342+
data: encodeFunctionData({
343+
abi: pool.abi,
344+
functionName: 'removeFromAllowList',
345+
args: [addr],
346+
}),
347+
value: 0n,
348+
})),
349+
});
350+
});

utils/arguments.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ export const stringToAddress = (value: string): Address => {
196196
return value;
197197
};
198198

199+
export const stringArrayToAddressArray = (
200+
value: string,
201+
previous: Address[],
202+
) => {
203+
return previous.concat([stringToAddress(value)]);
204+
};
205+
199206
export const stringToHash = (value: string): Hex => {
200207
if (!isHex(value)) {
201208
program.error('Hash value must be a valid hash', { exitCode: 1 });

0 commit comments

Comments
 (0)