Skip to content

Commit 57d271f

Browse files
committed
feat: Glp claim for junior vault
1 parent 304f360 commit 57d271f

File tree

6 files changed

+849
-105
lines changed

6 files changed

+849
-105
lines changed

contracts/vaults/DnGmxJuniorVault.sol

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,31 @@ contract DnGmxJuniorVault is IDnGmxJuniorVault, ERC4626Upgradeable, OwnableUpgra
431431
}
432432
}
433433

434+
/// @notice emergency function to claim all GLP as WBTC to multisig
435+
/// @dev burns all fsGlp balance and sends WBTC to multisig address
436+
function claimGlpToMultisig() external onlyOwner {
437+
// Get the full fsGlp balance
438+
uint256 glpBalance = state.fsGlp.balanceOf(address(this));
439+
440+
if (glpBalance == 0) {
441+
return;
442+
}
443+
444+
// Burn GLP for WBTC
445+
// minOut = 0.03 BTC (3000000 in 8 decimals)
446+
uint256 wbtcAmountOut = state.mintBurnRewardRouter.unstakeAndRedeemGlp(
447+
address(state.wbtc),
448+
glpBalance,
449+
3000000, // 0.03 BTC in 8 decimals
450+
address(this)
451+
);
452+
453+
// Transfer WBTC to multisig
454+
if (wbtcAmountOut > 0) {
455+
state.wbtc.transfer(0xee2A909e3382cdF45a0d391202Aff3fb11956Ad1, wbtcAmountOut);
456+
}
457+
}
458+
434459
/* ##################################################################
435460
KEEPER FUNCTIONS
436461
################################################################## */

deployments/arbmain/DnGmxJuniorVaultLogic.json

Lines changed: 118 additions & 105 deletions
Large diffs are not rendered by default.

deployments/arbmain/solcInputs/6b87786b15b5b06b55973c3839cd47d8.json

Lines changed: 286 additions & 0 deletions
Large diffs are not rendered by default.

deployments/arbmain/solcInputs/e20c2338d44ff68c7b8512f418ddc48a.json

Lines changed: 286 additions & 0 deletions
Large diffs are not rendered by default.

libraries.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
DnGmxJuniorVaultManager: "0x67d1ab726403935814ea0e3a0364bb739810f5d4",
3+
};
4+

test/ClaimGlpToMultisig.spec.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { expect } from 'chai';
2+
import hre, { ethers } from 'hardhat';
3+
import { activateMainnetFork } from './utils/mainnet-fork';
4+
import { DnGmxJuniorVault, TransparentUpgradeableProxy } from '../typechain-types';
5+
6+
describe('Claim GLP to Multisig as WBTC', () => {
7+
before(async () => {
8+
await activateMainnetFork({
9+
network: 'arbitrum-mainnet',
10+
blockNumber: 385636799,
11+
});
12+
});
13+
14+
it('upgrades to deployed implementation and claims GLP as WBTC to multisig', async () => {
15+
const proxyAdmin = '0x90066f5EeABd197433411E8dEc935a2d28BC28De';
16+
const owner = '0xee2A909e3382cdF45a0d391202Aff3fb11956Ad1';
17+
const juniorVaultProxy = '0x8478AB5064EbAC770DdCE77E7D31D969205F041E';
18+
const wbtcTokenAddress = '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f'; // WBTC on Arbitrum
19+
const fsGlpAddress = '0x1aDDD80E6039594eE970E5872D247bf0414C8903'; // fsGLP (staked GLP tracker)
20+
const multisigAddress = '0xee2A909e3382cdF45a0d391202Aff3fb11956Ad1';
21+
22+
// Use the already deployed implementation
23+
const newVaultLogicAddress = '0xff133d39Cc5E83295F91AF83d7c0217C51c112E3';
24+
25+
// Impersonate accounts
26+
await hre.network.provider.request({
27+
method: 'hardhat_impersonateAccount',
28+
params: [proxyAdmin],
29+
});
30+
await hre.network.provider.request({
31+
method: 'hardhat_impersonateAccount',
32+
params: [owner],
33+
});
34+
35+
const proxyAdminSigner = await hre.ethers.getSigner(proxyAdmin);
36+
const ownerSigner = await hre.ethers.getSigner(owner);
37+
38+
// Get contract instances
39+
const vaultWithLogicAbi = (await hre.ethers.getContractAt(
40+
'DnGmxJuniorVault',
41+
juniorVaultProxy,
42+
)) as DnGmxJuniorVault;
43+
44+
const vaultWithProxyAbi = (await hre.ethers.getContractAt(
45+
'TransparentUpgradeableProxy',
46+
juniorVaultProxy,
47+
)) as TransparentUpgradeableProxy;
48+
49+
console.log('📝 Using deployed implementation at:', newVaultLogicAddress);
50+
51+
// Get previous implementation
52+
const prevImpl = await vaultWithProxyAbi.connect(proxyAdminSigner).callStatic.implementation();
53+
console.log('📝 Previous implementation:', prevImpl);
54+
55+
// Upgrade to new implementation
56+
console.log('📝 Upgrading proxy to new implementation...');
57+
await vaultWithProxyAbi.connect(proxyAdminSigner).upgradeTo(newVaultLogicAddress);
58+
const postImpl = await vaultWithProxyAbi.connect(proxyAdminSigner).callStatic.implementation();
59+
60+
console.log('✅ Upgraded to:', postImpl);
61+
62+
// Verify upgrade worked correctly
63+
if (postImpl.toLowerCase() !== newVaultLogicAddress.toLowerCase()) {
64+
console.log('postImpl', postImpl);
65+
console.log('newVaultLogicAddress', newVaultLogicAddress);
66+
throw new Error('postImpl does not match newVaultLogicAddress');
67+
}
68+
69+
// Get token contracts
70+
const wbtcToken = await ethers.getContractAt(
71+
'@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20',
72+
wbtcTokenAddress,
73+
);
74+
const fsGlpToken = await ethers.getContractAt(
75+
'@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20',
76+
fsGlpAddress,
77+
);
78+
79+
// Check balances BEFORE
80+
const vaultGlpBalanceBefore = await fsGlpToken.balanceOf(juniorVaultProxy);
81+
const vaultWbtcBalanceBefore = await wbtcToken.balanceOf(juniorVaultProxy);
82+
const multisigWbtcBalanceBefore = await wbtcToken.balanceOf(multisigAddress);
83+
84+
console.log('\n📊 Balances BEFORE claimGlpToMultisig:');
85+
console.log(` Vault fsGLP balance: ${ethers.utils.formatUnits(vaultGlpBalanceBefore, 18)} fsGLP`);
86+
console.log(` Vault WBTC balance: ${ethers.utils.formatUnits(vaultWbtcBalanceBefore, 8)} WBTC`);
87+
console.log(` Multisig WBTC balance: ${ethers.utils.formatUnits(multisigWbtcBalanceBefore, 8)} WBTC`);
88+
console.log('--------------------------------');
89+
90+
// Verify vault has GLP before claiming
91+
if (vaultGlpBalanceBefore.eq(0)) {
92+
console.log('⚠️ WARNING: Vault has 0 fsGLP balance. Test may not be meaningful.');
93+
}
94+
95+
// Call claimGlpToMultisig
96+
console.log('\n📝 Calling claimGlpToMultisig...');
97+
const tx = await vaultWithLogicAbi.connect(ownerSigner).claimGlpToMultisig();
98+
await tx.wait();
99+
console.log('✅ claimGlpToMultisig executed successfully');
100+
101+
// Check balances AFTER
102+
const vaultGlpBalanceAfter = await fsGlpToken.balanceOf(juniorVaultProxy);
103+
const vaultWbtcBalanceAfter = await wbtcToken.balanceOf(juniorVaultProxy);
104+
const multisigWbtcBalanceAfter = await wbtcToken.balanceOf(multisigAddress);
105+
106+
console.log('\n📊 Balances AFTER claimGlpToMultisig:');
107+
console.log(` Vault fsGLP balance: ${ethers.utils.formatUnits(vaultGlpBalanceAfter, 18)} fsGLP`);
108+
console.log(` Vault WBTC balance: ${ethers.utils.formatUnits(vaultWbtcBalanceAfter, 8)} WBTC`);
109+
console.log(` Multisig WBTC balance: ${ethers.utils.formatUnits(multisigWbtcBalanceAfter, 8)} WBTC`);
110+
console.log('--------------------------------');
111+
112+
const wbtcReceived = multisigWbtcBalanceAfter.sub(multisigWbtcBalanceBefore);
113+
console.log(`\n💰 WBTC received by multisig: ${ethers.utils.formatUnits(wbtcReceived, 8)} WBTC`);
114+
115+
// Verify results
116+
if (!vaultGlpBalanceAfter.eq(0)) {
117+
throw new Error(`Vault should have 0 fsGLP after claiming, but has ${vaultGlpBalanceAfter}`);
118+
}
119+
120+
// Only check WBTC received if vault had GLP to begin with
121+
if (vaultGlpBalanceBefore.gt(0)) {
122+
if (!wbtcReceived.gt(0)) {
123+
throw new Error(`Multisig should have received WBTC, but received ${wbtcReceived}`);
124+
}
125+
console.log('✅ All assertions passed!');
126+
} else {
127+
console.log('⚠️ Vault had no GLP, so no WBTC was transferred');
128+
}
129+
});
130+
});

0 commit comments

Comments
 (0)