@sage-protocol/cli 0.3.6 → 0.3.9
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/dist/cli/commands/boost.js +76 -68
- package/dist/cli/commands/bounty.js +123 -85
- package/dist/cli/commands/config.js +2 -0
- package/dist/cli/commands/doctor.js +18 -7
- package/dist/cli/commands/personal.js +64 -78
- package/dist/cli/commands/premium-pre.js +23 -875
- package/dist/cli/commands/premium.js +237 -667
- package/dist/cli/commands/prompts.js +6 -1
- package/dist/cli/commands/sxxx.js +103 -0
- package/dist/cli/commands/timelock.js +22 -192
- package/dist/cli/index.js +1 -5
- package/dist/cli/utils/aliases.js +3 -1
- package/dist/cli/utils/error-handler.js +7 -13
- package/dist/cli/utils/lit.js +103 -0
- package/dist/ops/config/env/load-env.sepolia.sh +4 -4
- package/package.json +1 -1
|
@@ -41,7 +41,7 @@ function register(program) {
|
|
|
41
41
|
// ===== Manager-type preflight (DIRECT vs MERKLE) =====
|
|
42
42
|
const detectManagerType = async (address) => {
|
|
43
43
|
const directIface = new ethers.Interface([
|
|
44
|
-
'function getBoost(uint256) view returns (address,address,uint256,uint256,uint256,uint256,uint96,uint8,address,bool,bool)'
|
|
44
|
+
'function getBoost(uint256) view returns (tuple(address creator, address governor, uint256 proposalId, uint256 snapshot, uint256 perVoter, uint256 maxVoters, uint256 votersPaid, uint96 minVotes, uint8 payoutMode, uint8 support, uint256 startAt, uint256 expiresAt, uint256 totalPool, uint256 totalPaid, uint8 kind, address policy, bool active, bool paused) boost)'
|
|
45
45
|
]);
|
|
46
46
|
const merkleIface = new ethers.Interface([
|
|
47
47
|
'function getBoost(uint256) view returns (uint256,uint256,bytes32,bool,bool,address)'
|
|
@@ -78,20 +78,20 @@ function register(program) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const mapKind = (k) => {
|
|
81
|
-
const v = String(k||'').toLowerCase();
|
|
81
|
+
const v = String(k || '').toLowerCase();
|
|
82
82
|
if (v === 'direct') return 0; // EligibilityKind.DIRECT
|
|
83
83
|
if (v === 'merkle') return 1; // EligibilityKind.MERKLE
|
|
84
84
|
if (v === 'custom') return 2; // EligibilityKind.CUSTOM
|
|
85
85
|
throw new Error(`Unknown kind: ${k}`);
|
|
86
86
|
};
|
|
87
87
|
const mapPayout = (m) => {
|
|
88
|
-
const v = String(m||'').toLowerCase();
|
|
88
|
+
const v = String(m || '').toLowerCase();
|
|
89
89
|
if (v === 'fixed') return 0; // PayoutMode.FIXED
|
|
90
90
|
if (v === 'variable') return 1;// PayoutMode.VARIABLE
|
|
91
91
|
throw new Error(`Unknown payout-mode: ${m}`);
|
|
92
92
|
};
|
|
93
93
|
const mapSupport = (s) => {
|
|
94
|
-
const v = String(s||'').toLowerCase();
|
|
94
|
+
const v = String(s || '').toLowerCase();
|
|
95
95
|
if (v === 'any') return 0; // EligibilitySupport.Any
|
|
96
96
|
if (v === 'for') return 1; // EligibilitySupport.ForOnly
|
|
97
97
|
throw new Error(`Unknown support: ${s}`);
|
|
@@ -116,7 +116,7 @@ function register(program) {
|
|
|
116
116
|
|
|
117
117
|
// Preflight checks
|
|
118
118
|
const owner = await signer.getAddress();
|
|
119
|
-
const nowTs = BigInt(Math.floor(Date.now()/1000));
|
|
119
|
+
const nowTs = BigInt(Math.floor(Date.now() / 1000));
|
|
120
120
|
if (startAt && expiresAt && expiresAt <= startAt) {
|
|
121
121
|
console.log('⚠️ expires-at <= start-at; window may be invalid');
|
|
122
122
|
}
|
|
@@ -149,54 +149,56 @@ function register(program) {
|
|
|
149
149
|
'function nonces(address) view returns (uint256)',
|
|
150
150
|
'function permit(address,address,uint256,uint256,uint8,bytes32,bytes32)'
|
|
151
151
|
], signer);
|
|
152
|
-
const balance = await usdc.balanceOf(owner).catch(()=>0n);
|
|
152
|
+
const balance = await usdc.balanceOf(owner).catch(() => 0n);
|
|
153
153
|
if (balance < totalPool) console.log(`⚠️ USDC balance ${balance.toString()} < required ${totalPool.toString()}`);
|
|
154
|
-
let allowance = await usdc.allowance(owner, mgrAddr).catch(()=>0n);
|
|
154
|
+
let allowance = await usdc.allowance(owner, mgrAddr).catch(() => 0n);
|
|
155
155
|
if (allowance < totalPool) {
|
|
156
156
|
const wantPermit = !!opts.permit || process.env.SAGE_USE_PERMIT === '1' || process.env.SAGE_USE_PERMIT === 'true';
|
|
157
157
|
if (wantPermit) {
|
|
158
158
|
try {
|
|
159
159
|
const chain = await provider.getNetwork();
|
|
160
|
-
const name = await usdc.name().catch(()=> 'Token');
|
|
160
|
+
const name = await usdc.name().catch(() => 'Token');
|
|
161
161
|
const nonce = await usdc.nonces(owner);
|
|
162
|
-
const deadline = BigInt(Math.floor(Date.now()/1000) + 3600);
|
|
162
|
+
const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);
|
|
163
163
|
const domain = { name, version: '1', chainId: Number(chain.chainId), verifyingContract: usdcAddr };
|
|
164
|
-
const types = {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
const types = {
|
|
165
|
+
Permit: [
|
|
166
|
+
{ name: 'owner', type: 'address' },
|
|
167
|
+
{ name: 'spender', type: 'address' },
|
|
168
|
+
{ name: 'value', type: 'uint256' },
|
|
169
|
+
{ name: 'nonce', type: 'uint256' },
|
|
170
|
+
{ name: 'deadline', type: 'uint256' }
|
|
171
|
+
]
|
|
172
|
+
};
|
|
171
173
|
const value = { owner, spender: mgrAddr, value: totalPool, nonce, deadline };
|
|
172
174
|
const sig = await signer.signTypedData(domain, types, value);
|
|
173
175
|
const { v, r, s } = ethers.Signature.from(sig);
|
|
174
176
|
const txp = await usdc.permit(owner, mgrAddr, totalPool, deadline, v, r, s);
|
|
175
177
|
{ const { waitForReceipt } = require('../utils/tx-wait'); const { ethers } = require('ethers'); const pr = new ethers.JsonRpcProvider(process.env.RPC_URL || process.env.BASE_SEPOLIA_RPC || process.env.BASE_RPC_URL || 'https://base-sepolia.publicnode.com'); await waitForReceipt(pr, txp, Number(process.env.SAGE_TX_WAIT_MS || 60000)); }
|
|
176
178
|
console.log('✅ Permit submitted');
|
|
177
|
-
allowance = await usdc.allowance(owner, mgrAddr).catch(()=>0n);
|
|
179
|
+
allowance = await usdc.allowance(owner, mgrAddr).catch(() => 0n);
|
|
178
180
|
} catch (e) {
|
|
179
181
|
console.log('⚠️ Permit failed or unsupported, falling back to approve:', e.message);
|
|
180
182
|
}
|
|
181
183
|
}
|
|
182
184
|
if (allowance < totalPool) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
185
|
+
console.log('💳 Approving USDC to DIRECT manager');
|
|
186
|
+
console.log(` token: ${usdcAddr}`);
|
|
187
|
+
console.log(` owner: ${owner}`);
|
|
188
|
+
console.log(` spender: ${mgrAddr}`);
|
|
189
|
+
console.log(` need: ${totalPool.toString()} current: ${allowance.toString()}`);
|
|
190
|
+
const txa = await usdc.approve(mgrAddr, totalPool); { const { waitForReceipt } = require('../utils/tx-wait'); const { ethers } = require('ethers'); const pr = new ethers.JsonRpcProvider(process.env.RPC_URL || process.env.BASE_SEPOLIA_RPC || process.env.BASE_RPC_URL || 'https://base-sepolia.publicnode.com'); await waitForReceipt(pr, txa, Number(process.env.SAGE_TX_WAIT_MS || 60000)); }
|
|
191
|
+
console.log('✅ Approve confirmed');
|
|
190
192
|
}
|
|
191
193
|
} else {
|
|
192
194
|
console.log(`✅ USDC allowance sufficient: ${allowance.toString()} (need ${totalPool.toString()})`);
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
const iface = new ethers.Interface([
|
|
196
|
-
'function createBoost(address,uint256,uint256,uint256,uint8,address,uint96,uint8,uint8,uint256,uint256)'
|
|
198
|
+
'function createBoost(tuple(address governor, uint256 proposalId, uint256 perVoter, uint256 maxVoters, uint8 kind, address policy, uint96 minVotes, uint8 payoutMode, uint8 support, uint256 startAt, uint256 expiresAt) params)'
|
|
197
199
|
]);
|
|
198
200
|
|
|
199
|
-
const
|
|
201
|
+
const params = [
|
|
200
202
|
opts.governor,
|
|
201
203
|
BigInt(opts.proposalId),
|
|
202
204
|
perVoter,
|
|
@@ -208,10 +210,11 @@ function register(program) {
|
|
|
208
210
|
support,
|
|
209
211
|
startAt,
|
|
210
212
|
expiresAt,
|
|
211
|
-
]
|
|
213
|
+
];
|
|
214
|
+
const data = iface.encodeFunctionData('createBoost', [params]);
|
|
212
215
|
const tx = await signer.sendTransaction({ to: mgrAddr, data });
|
|
213
216
|
console.log('tx:', tx.hash);
|
|
214
|
-
} catch (e) { console.error('❌ create failed:', e.message); process.exit(1);}
|
|
217
|
+
} catch (e) { console.error('❌ create failed:', e.message); process.exit(1); }
|
|
215
218
|
});
|
|
216
219
|
|
|
217
220
|
// New helper: set root on MerkleEligibilityPolicy adapter
|
|
@@ -231,7 +234,7 @@ function register(program) {
|
|
|
231
234
|
|
|
232
235
|
if (opts.policy && opts.policy !== ethers.ZeroAddress) {
|
|
233
236
|
const iface = new ethers.Interface(['function setRoot(uint256,bytes32)']);
|
|
234
|
-
const tx = await signer.sendTransaction({ to: opts.policy, data: iface.encodeFunctionData('setRoot',[id, opts.root]) });
|
|
237
|
+
const tx = await signer.sendTransaction({ to: opts.policy, data: iface.encodeFunctionData('setRoot', [id, opts.root]) });
|
|
235
238
|
console.log('tx:', tx.hash);
|
|
236
239
|
return;
|
|
237
240
|
}
|
|
@@ -242,9 +245,9 @@ function register(program) {
|
|
|
242
245
|
}
|
|
243
246
|
// Call manager.setMerkleRoot
|
|
244
247
|
const ifMgr = new ethers.Interface(['function setMerkleRoot(uint256,bytes32)']);
|
|
245
|
-
const tx = await signer.sendTransaction({ to: mgrAddr, data: ifMgr.encodeFunctionData('setMerkleRoot',[id, opts.root]) });
|
|
248
|
+
const tx = await signer.sendTransaction({ to: mgrAddr, data: ifMgr.encodeFunctionData('setMerkleRoot', [id, opts.root]) });
|
|
246
249
|
console.log('tx:', tx.hash);
|
|
247
|
-
} catch (e) { console.error('❌ set-root failed:', e.message); process.exit(1);}
|
|
250
|
+
} catch (e) { console.error('❌ set-root failed:', e.message); process.exit(1); }
|
|
248
251
|
});
|
|
249
252
|
|
|
250
253
|
// Deprecated: legacy setter on old manager; keep for guidance
|
|
@@ -263,7 +266,7 @@ function register(program) {
|
|
|
263
266
|
const id = BigInt(opts.proposalId);
|
|
264
267
|
if (opts.policy && opts.policy !== ethers.ZeroAddress) {
|
|
265
268
|
const iface = new ethers.Interface(['function setRoot(uint256,bytes32)']);
|
|
266
|
-
const tx = await signer.sendTransaction({ to: opts.policy, data: iface.encodeFunctionData('setRoot',[id, opts.root]) });
|
|
269
|
+
const tx = await signer.sendTransaction({ to: opts.policy, data: iface.encodeFunctionData('setRoot', [id, opts.root]) });
|
|
267
270
|
console.log('tx:', tx.hash);
|
|
268
271
|
console.log('ℹ️ Note: set-merkle-root is deprecated; use boost set-root going forward.');
|
|
269
272
|
return;
|
|
@@ -271,14 +274,14 @@ function register(program) {
|
|
|
271
274
|
const mgr = opts.manager || process.env.BOOST_MANAGER_ADDRESS;
|
|
272
275
|
if (mgr && mgr !== ethers.ZeroAddress) {
|
|
273
276
|
const ifMgr = new ethers.Interface(['function setMerkleRoot(uint256,bytes32)']);
|
|
274
|
-
const tx = await signer.sendTransaction({ to: mgr, data: ifMgr.encodeFunctionData('setMerkleRoot',[id, opts.root]) });
|
|
277
|
+
const tx = await signer.sendTransaction({ to: mgr, data: ifMgr.encodeFunctionData('setMerkleRoot', [id, opts.root]) });
|
|
275
278
|
console.log('tx:', tx.hash);
|
|
276
279
|
console.log('ℹ️ Note: set-merkle-root is deprecated; use boost set-root going forward.');
|
|
277
280
|
return;
|
|
278
281
|
}
|
|
279
282
|
console.error('❌ set-merkle-root is deprecated. Use: boost set-root --policy <address> --proposal-id <id> --root <hex32>');
|
|
280
283
|
process.exit(1);
|
|
281
|
-
} catch (e) { console.error('❌ set-merkle-root failed:', e.message); process.exit(1);}
|
|
284
|
+
} catch (e) { console.error('❌ set-merkle-root failed:', e.message); process.exit(1); }
|
|
282
285
|
});
|
|
283
286
|
|
|
284
287
|
boost
|
|
@@ -294,27 +297,30 @@ function register(program) {
|
|
|
294
297
|
const mgrAddr = opts.manager || process.env.BOOST_MANAGER_ADDRESS;
|
|
295
298
|
const id = BigInt(opts.proposalId);
|
|
296
299
|
const ifMerkle = new ethers.Interface(['function getBoost(uint256) view returns (uint256,uint256,bytes32,bool,bool,address)']);
|
|
297
|
-
const ifDirect = new ethers.Interface(['function getBoost(uint256) view returns (address,address,uint256,uint256,uint256,uint256,uint96,uint8,address,bool,bool)']);
|
|
300
|
+
const ifDirect = new ethers.Interface(['function getBoost(uint256) view returns (tuple(address creator, address governor, uint256 proposalId, uint256 snapshot, uint256 perVoter, uint256 maxVoters, uint256 votersPaid, uint96 minVotes, uint8 payoutMode, uint8 support, uint256 startAt, uint256 expiresAt, uint256 totalPool, uint256 totalPaid, uint8 kind, address policy, bool active, bool paused) boost)']);
|
|
298
301
|
// Try DIRECT first
|
|
299
302
|
try {
|
|
300
|
-
const retD = await provider.call({ to: mgrAddr, data: ifDirect.encodeFunctionData('getBoost',[id]) });
|
|
301
|
-
const [
|
|
303
|
+
const retD = await provider.call({ to: mgrAddr, data: ifDirect.encodeFunctionData('getBoost', [id]) });
|
|
304
|
+
const [b] = ifDirect.decodeFunctionResult('getBoost', retD);
|
|
302
305
|
console.log(JSON.stringify({
|
|
303
306
|
managerType: 'direct', proposalId: opts.proposalId,
|
|
304
|
-
creator, governor, snapshot: snapshot.toString(), perVoter: perVoter.toString(),
|
|
305
|
-
maxVoters: maxVoters.toString(), votersPaid: votersPaid.toString(), minVotes: Number(minVotes),
|
|
306
|
-
kind: Number(kind), policy, active, paused
|
|
307
|
+
creator: b.creator, governor: b.governor, snapshot: b.snapshot.toString(), perVoter: b.perVoter.toString(),
|
|
308
|
+
maxVoters: b.maxVoters.toString(), votersPaid: b.votersPaid.toString(), minVotes: Number(b.minVotes),
|
|
309
|
+
kind: Number(b.kind), policy: b.policy, active: b.active, paused: b.paused,
|
|
310
|
+
payoutMode: Number(b.payoutMode), support: Number(b.support),
|
|
311
|
+
startAt: b.startAt.toString(), expiresAt: b.expiresAt.toString(),
|
|
312
|
+
totalPool: b.totalPool.toString(), totalPaid: b.totalPaid.toString()
|
|
307
313
|
}, null, 2));
|
|
308
314
|
} catch (_) {
|
|
309
315
|
// Fallback to MERKLE
|
|
310
|
-
const retM = await provider.call({ to: mgrAddr, data: ifMerkle.encodeFunctionData('getBoost',[id]) });
|
|
311
|
-
const [totalPool,totalClaimed,merkleRoot,active,finalized,creator] = ifMerkle.decodeFunctionResult('getBoost', retM);
|
|
316
|
+
const retM = await provider.call({ to: mgrAddr, data: ifMerkle.encodeFunctionData('getBoost', [id]) });
|
|
317
|
+
const [totalPool, totalClaimed, merkleRoot, active, finalized, creator] = ifMerkle.decodeFunctionResult('getBoost', retM);
|
|
312
318
|
console.log(JSON.stringify({
|
|
313
319
|
managerType: 'merkle', proposalId: opts.proposalId,
|
|
314
320
|
totalPool: totalPool.toString(), totalClaimed: totalClaimed.toString(), merkleRoot, active, finalized, creator
|
|
315
321
|
}, null, 2));
|
|
316
322
|
}
|
|
317
|
-
} catch (e) { console.error('❌ status failed:', e.message); process.exit(1);}
|
|
323
|
+
} catch (e) { console.error('❌ status failed:', e.message); process.exit(1); }
|
|
318
324
|
});
|
|
319
325
|
|
|
320
326
|
boost
|
|
@@ -333,18 +339,18 @@ function register(program) {
|
|
|
333
339
|
// Manager-type preflight + helpful hint if mismatched
|
|
334
340
|
const detectManagerType = async (address) => {
|
|
335
341
|
const directIface = new ethers.Interface([
|
|
336
|
-
'function getBoost(uint256) view returns (address,address,uint256,uint256,uint256,uint256,uint96,uint8,address,bool,bool)'
|
|
342
|
+
'function getBoost(uint256) view returns (tuple(address creator, address governor, uint256 proposalId, uint256 snapshot, uint256 perVoter, uint256 maxVoters, uint256 votersPaid, uint96 minVotes, uint8 payoutMode, uint8 support, uint256 startAt, uint256 expiresAt, uint256 totalPool, uint256 totalPaid, uint8 kind, address policy, bool active, bool paused) boost)'
|
|
337
343
|
]);
|
|
338
344
|
const merkleIface = new ethers.Interface([
|
|
339
345
|
'function getBoost(uint256) view returns (uint256,uint256,bytes32,bool,bool,address)'
|
|
340
346
|
]);
|
|
341
347
|
try {
|
|
342
|
-
const retD = await provider.call({ to: address, data: directIface.encodeFunctionData('getBoost',[0n]) });
|
|
348
|
+
const retD = await provider.call({ to: address, data: directIface.encodeFunctionData('getBoost', [0n]) });
|
|
343
349
|
directIface.decodeFunctionResult('getBoost', retD);
|
|
344
350
|
return 'direct';
|
|
345
351
|
} catch (_) {
|
|
346
352
|
try {
|
|
347
|
-
const retM = await provider.call({ to: address, data: merkleIface.encodeFunctionData('getBoost',[0n]) });
|
|
353
|
+
const retM = await provider.call({ to: address, data: merkleIface.encodeFunctionData('getBoost', [0n]) });
|
|
348
354
|
merkleIface.decodeFunctionResult('getBoost', retM);
|
|
349
355
|
return 'merkle';
|
|
350
356
|
} catch (_) { return 'unknown'; }
|
|
@@ -356,16 +362,16 @@ function register(program) {
|
|
|
356
362
|
let looksEmpty = false;
|
|
357
363
|
if (mgrType === 'direct') {
|
|
358
364
|
try {
|
|
359
|
-
const ifD = new ethers.Interface(['function getBoost(uint256) view returns (address,address,uint256,uint256,uint256,uint256,uint96,uint8,address,bool,bool)']);
|
|
360
|
-
const ret = await provider.call({ to: mgrAddr, data: ifD.encodeFunctionData('getBoost',[id]) });
|
|
361
|
-
const [
|
|
362
|
-
looksEmpty = (creator === ethers.ZeroAddress) || !active;
|
|
365
|
+
const ifD = new ethers.Interface(['function getBoost(uint256) view returns (tuple(address creator, address governor, uint256 proposalId, uint256 snapshot, uint256 perVoter, uint256 maxVoters, uint256 votersPaid, uint96 minVotes, uint8 payoutMode, uint8 support, uint256 startAt, uint256 expiresAt, uint256 totalPool, uint256 totalPaid, uint8 kind, address policy, bool active, bool paused) boost)']);
|
|
366
|
+
const ret = await provider.call({ to: mgrAddr, data: ifD.encodeFunctionData('getBoost', [id]) });
|
|
367
|
+
const [b] = ifD.decodeFunctionResult('getBoost', ret);
|
|
368
|
+
looksEmpty = (b.creator === ethers.ZeroAddress) || !b.active;
|
|
363
369
|
} catch (_) { /* ignore */ }
|
|
364
370
|
} else if (mgrType === 'merkle') {
|
|
365
371
|
try {
|
|
366
372
|
const ifM = new ethers.Interface(['function getBoost(uint256) view returns (uint256,uint256,bytes32,bool,bool,address)']);
|
|
367
|
-
const ret = await provider.call({ to: mgrAddr, data: ifM.encodeFunctionData('getBoost',[id]) });
|
|
368
|
-
const [totalPool
|
|
373
|
+
const ret = await provider.call({ to: mgrAddr, data: ifM.encodeFunctionData('getBoost', [id]) });
|
|
374
|
+
const [totalPool, , , active] = ifM.decodeFunctionResult('getBoost', ret);
|
|
369
375
|
looksEmpty = (totalPool === 0n) || !active;
|
|
370
376
|
} catch (_) { /* ignore */ }
|
|
371
377
|
}
|
|
@@ -377,9 +383,9 @@ function register(program) {
|
|
|
377
383
|
}
|
|
378
384
|
|
|
379
385
|
const iface = new ethers.Interface(['function finalize(uint256)']);
|
|
380
|
-
const tx = await signer.sendTransaction({ to: mgrAddr, data: iface.encodeFunctionData('finalize',[id]) });
|
|
386
|
+
const tx = await signer.sendTransaction({ to: mgrAddr, data: iface.encodeFunctionData('finalize', [id]) });
|
|
381
387
|
console.log('tx:', tx.hash);
|
|
382
|
-
} catch (e) { console.error('❌ finalize failed:', e.message); process.exit(1);}
|
|
388
|
+
} catch (e) { console.error('❌ finalize failed:', e.message); process.exit(1); }
|
|
383
389
|
});
|
|
384
390
|
|
|
385
391
|
boost
|
|
@@ -402,9 +408,9 @@ function register(program) {
|
|
|
402
408
|
}
|
|
403
409
|
const proof = JSON.parse(proofStr);
|
|
404
410
|
const iface = new ethers.Interface(['function claim(uint256,address,uint256,bytes32[])']);
|
|
405
|
-
const tx = await signer.sendTransaction({ to: mgrAddr, data: iface.encodeFunctionData('claim',[BigInt(opts.proposalId), await signer.getAddress(), BigInt(opts.amount), proof]) });
|
|
411
|
+
const tx = await signer.sendTransaction({ to: mgrAddr, data: iface.encodeFunctionData('claim', [BigInt(opts.proposalId), await signer.getAddress(), BigInt(opts.amount), proof]) });
|
|
406
412
|
console.log('tx:', tx.hash);
|
|
407
|
-
} catch (e) { console.error('❌ claim failed:', e.message); process.exit(1);}
|
|
413
|
+
} catch (e) { console.error('❌ claim failed:', e.message); process.exit(1); }
|
|
408
414
|
});
|
|
409
415
|
|
|
410
416
|
// New: fund a Merkle boost pool and create boost entry
|
|
@@ -429,7 +435,7 @@ function register(program) {
|
|
|
429
435
|
// Sanity: detect manager is Merkle flavor
|
|
430
436
|
try {
|
|
431
437
|
const ifMerkle = new ethers.Interface(['function getBoost(uint256) view returns (uint256,uint256,bytes32,bool,bool,address)']);
|
|
432
|
-
await provider.call({ to: mgrAddr, data: ifMerkle.encodeFunctionData('getBoost',[0n]) });
|
|
438
|
+
await provider.call({ to: mgrAddr, data: ifMerkle.encodeFunctionData('getBoost', [0n]) });
|
|
433
439
|
} catch (_) {
|
|
434
440
|
console.warn('⚠️ Manager at', mgrAddr, 'does not look like Merkle manager; proceeding anyway');
|
|
435
441
|
}
|
|
@@ -451,17 +457,19 @@ function register(program) {
|
|
|
451
457
|
if (wantPermit) {
|
|
452
458
|
try {
|
|
453
459
|
const chain = await provider.getNetwork();
|
|
454
|
-
const name = await usdc.name().catch(()=> 'Token');
|
|
460
|
+
const name = await usdc.name().catch(() => 'Token');
|
|
455
461
|
const nonce = await usdc.nonces(signerAddr);
|
|
456
|
-
const deadline = BigInt(Math.floor(Date.now()/1000) + 3600);
|
|
462
|
+
const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);
|
|
457
463
|
const domain = { name, version: '1', chainId: Number(chain.chainId), verifyingContract: usdcAddr };
|
|
458
|
-
const types = {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
464
|
+
const types = {
|
|
465
|
+
Permit: [
|
|
466
|
+
{ name: 'owner', type: 'address' },
|
|
467
|
+
{ name: 'spender', type: 'address' },
|
|
468
|
+
{ name: 'value', type: 'uint256' },
|
|
469
|
+
{ name: 'nonce', type: 'uint256' },
|
|
470
|
+
{ name: 'deadline', type: 'uint256' }
|
|
471
|
+
]
|
|
472
|
+
};
|
|
465
473
|
const value = { owner: signerAddr, spender: mgrAddr, value: amount, nonce, deadline };
|
|
466
474
|
const sig = await signer.signTypedData(domain, types, value);
|
|
467
475
|
const { v, r, s } = ethers.Signature.from(sig);
|
|
@@ -480,9 +488,9 @@ function register(program) {
|
|
|
480
488
|
}
|
|
481
489
|
}
|
|
482
490
|
const ifMgr = new ethers.Interface(['function createBoost(uint256,uint256)']);
|
|
483
|
-
const tx = await signer.sendTransaction({ to: mgrAddr, data: ifMgr.encodeFunctionData('createBoost',[BigInt(opts.proposalId), amount]) });
|
|
491
|
+
const tx = await signer.sendTransaction({ to: mgrAddr, data: ifMgr.encodeFunctionData('createBoost', [BigInt(opts.proposalId), amount]) });
|
|
484
492
|
console.log('tx:', tx.hash);
|
|
485
|
-
} catch (e) { console.error('❌ fund failed:', e.message); process.exit(1);}
|
|
493
|
+
} catch (e) { console.error('❌ fund failed:', e.message); process.exit(1); }
|
|
486
494
|
});
|
|
487
495
|
|
|
488
496
|
program.addCommand(boost);
|