Skip to content

Commit 1c6109b

Browse files
committed
add tests
1 parent 8c90069 commit 1c6109b

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { prompt } from 'gluegun';
2+
import { describe, expect, it, vi } from 'vitest';
3+
import EthereumABI from '../protocols/ethereum/abi.js';
4+
import { ContractService } from './contracts.js';
5+
import { checkForProxy } from './proxy.js';
6+
import { loadRegistry } from './registry.js';
7+
8+
// Mock gluegun's prompt
9+
vi.mock('gluegun', async () => {
10+
const actual = await vi.importActual('gluegun');
11+
return {
12+
...actual,
13+
prompt: {
14+
confirm: vi.fn().mockResolvedValue(true),
15+
},
16+
};
17+
});
18+
19+
describe('Proxy detection', async () => {
20+
const NETWORK = 'mainnet';
21+
const registry = await loadRegistry();
22+
const contractService = new ContractService(registry);
23+
24+
interface ProxyTestCase {
25+
name: string;
26+
type: string;
27+
address: string;
28+
implementationAddress: string | null;
29+
expectedFunctions: string[];
30+
}
31+
32+
const testCases: ProxyTestCase[] = [
33+
{
34+
name: 'USDC',
35+
type: 'EIP-1967 Upgradeable',
36+
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
37+
implementationAddress: '0x43506849d7c04f9138d1a2050bbf3a0c054402dd',
38+
expectedFunctions: ['mint(address,uint256)', 'configureMinter(address,uint256)'],
39+
},
40+
{
41+
name: 'BUSD',
42+
type: 'OpenZeppelin Unstructured Storage',
43+
address: '0x4Fabb145d64652a948d72533023f6E7A623C7C53',
44+
implementationAddress: '0x2A3F1A37C04F82aA274f5353834B2d002Db91015',
45+
expectedFunctions: ['reclaimBUSD()', 'claimOwnership()'],
46+
},
47+
{
48+
name: 'Gelato',
49+
type: 'EIP-2535 Diamond Pattern (not supported)',
50+
address: '0x3caca7b48d0573d793d3b0279b5f0029180e83b6',
51+
implementationAddress: null,
52+
expectedFunctions: [],
53+
},
54+
];
55+
56+
for (const testCase of testCases) {
57+
it(`should handle ${testCase.name} ${testCase.type} Proxy`, async () => {
58+
const abi = await contractService.getABI(EthereumABI, NETWORK, testCase.address);
59+
expect(abi).toBeDefined();
60+
61+
const { implementationAddress, implementationAbi } = await checkForProxy(
62+
contractService,
63+
NETWORK,
64+
testCase.address,
65+
abi!,
66+
);
67+
68+
expect(implementationAddress === testCase.implementationAddress);
69+
70+
const implFunctions = implementationAbi?.callFunctionSignatures();
71+
for (const expectedFunction of testCase.expectedFunctions) {
72+
expect(implFunctions).toContain(expectedFunction);
73+
}
74+
});
75+
}
76+
77+
it('should handle when user declines to use implementation', async () => {
78+
vi.mocked(prompt.confirm).mockResolvedValueOnce(false);
79+
const abi = await contractService.getABI(EthereumABI, NETWORK, testCases[0].address);
80+
expect(abi).toBeDefined();
81+
82+
const { implementationAddress, implementationAbi } = await checkForProxy(
83+
contractService,
84+
NETWORK,
85+
testCases[0].address,
86+
abi!,
87+
);
88+
expect(implementationAddress).toBeNull();
89+
expect(implementationAbi).toBeNull();
90+
});
91+
});

0 commit comments

Comments
 (0)