mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
fix: remove contractErrors files accidentally merged into dev (#1923)
These files were part of PR #1911 (custom Solidity error decoding) which is not yet merged. They were accidentally included in the #1905 squash merge. The missing error-selector-map.json dependency breaks workspace CI (build, lint, type-check) across all branches.
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { humanizeContractError } from './contractErrors.js';
|
||||
|
||||
describe('humanizeContractError', () => {
|
||||
it('decodes a known custom error selector', () => {
|
||||
// 0xda7bd3a6 = InvalidVcAndDiscloseProof
|
||||
expect(humanizeContractError('0xda7bd3a6')).toBe('Invalid Vc And Disclose Proof');
|
||||
});
|
||||
|
||||
it('decodes a known SCREAMING_CASE selector', () => {
|
||||
// 0x034acfcc = REGISTERED_COMMITMENT
|
||||
expect(humanizeContractError('0x034acfcc')).toBe('Registered Commitment');
|
||||
});
|
||||
|
||||
it('decodes Error(string) standard revert', () => {
|
||||
// ABI encoding of Error("Insufficient balance")
|
||||
const encoded =
|
||||
'0x08c379a0' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000020' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000014' +
|
||||
'496e73756666696369656e742062616c616e636500000000000000000000000000';
|
||||
expect(humanizeContractError(encoded)).toBe('Insufficient balance');
|
||||
});
|
||||
|
||||
it('decodes Panic(uint256) arithmetic overflow', () => {
|
||||
const encoded =
|
||||
'0x4e487b71' + '0000000000000000000000000000000000000000000000000000000000000011';
|
||||
expect(humanizeContractError(encoded)).toBe('Arithmetic overflow or underflow');
|
||||
});
|
||||
|
||||
it('decodes Panic(uint256) division by zero', () => {
|
||||
const encoded =
|
||||
'0x4e487b71' + '0000000000000000000000000000000000000000000000000000000000000012';
|
||||
expect(humanizeContractError(encoded)).toBe('Division or modulo by zero');
|
||||
});
|
||||
|
||||
it('decodes Panic(uint256) array out of bounds', () => {
|
||||
const encoded =
|
||||
'0x4e487b71' + '0000000000000000000000000000000000000000000000000000000000000032';
|
||||
expect(humanizeContractError(encoded)).toBe('Array out of bounds');
|
||||
});
|
||||
|
||||
it('decodes Panic(uint256) unknown code gracefully', () => {
|
||||
const encoded =
|
||||
'0x4e487b71' + '00000000000000000000000000000000000000000000000000000000000000ff';
|
||||
expect(humanizeContractError(encoded)).toBe('Contract panic (code 255)');
|
||||
});
|
||||
|
||||
it('returns original string for unknown selector', () => {
|
||||
expect(humanizeContractError('0xdeadbeef')).toBe('0xdeadbeef');
|
||||
});
|
||||
|
||||
it('returns original string for non-hex input', () => {
|
||||
expect(humanizeContractError('something went wrong')).toBe('something went wrong');
|
||||
});
|
||||
|
||||
it('returns original string for empty input', () => {
|
||||
expect(humanizeContractError('')).toBe('');
|
||||
});
|
||||
|
||||
it('handles mixed-case selector input', () => {
|
||||
expect(humanizeContractError('0xDA7BD3A6')).toBe('Invalid Vc And Disclose Proof');
|
||||
});
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
import { AbiCoder } from 'ethers';
|
||||
|
||||
import selectorMap from '../data/error-selector-map.json' with { type: 'json' };
|
||||
|
||||
const SELECTOR_RE = /^0x[0-9a-fA-F]{8}/;
|
||||
const ERROR_STRING_SELECTOR = '0x08c379a0';
|
||||
const PANIC_SELECTOR = '0x4e487b71';
|
||||
|
||||
const PANIC_CODES: Record<number, string> = {
|
||||
0x01: 'Assertion failed',
|
||||
0x11: 'Arithmetic overflow or underflow',
|
||||
0x12: 'Division or modulo by zero',
|
||||
0x21: 'Invalid enum value',
|
||||
0x22: 'Corrupted storage byte array',
|
||||
0x31: 'Pop on empty array',
|
||||
0x32: 'Array out of bounds',
|
||||
0x41: 'Out of memory',
|
||||
0x51: 'Invalid internal function call',
|
||||
};
|
||||
|
||||
function formatErrorName(name: string): string {
|
||||
if (name === name.toUpperCase() && name.includes('_')) {
|
||||
return name
|
||||
.split('_')
|
||||
.map(word => word.charAt(0) + word.slice(1).toLowerCase())
|
||||
.join(' ');
|
||||
}
|
||||
return name.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a raw Solidity error string into a human-readable message.
|
||||
*
|
||||
* Handles:
|
||||
* - Standard Error(string): extracts the revert message
|
||||
* - Standard Panic(uint256): maps panic code to description
|
||||
* - Known custom error selectors from our contracts (auto-generated map)
|
||||
* - Unknown input: returned unchanged
|
||||
*/
|
||||
export function humanizeContractError(raw: string): string {
|
||||
if (!raw) return raw;
|
||||
|
||||
const lower = raw.toLowerCase();
|
||||
|
||||
if (lower.startsWith(ERROR_STRING_SELECTOR)) {
|
||||
try {
|
||||
const [message] = AbiCoder.defaultAbiCoder().decode(['string'], '0x' + raw.slice(10));
|
||||
return message as string;
|
||||
} catch {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
|
||||
if (lower.startsWith(PANIC_SELECTOR)) {
|
||||
try {
|
||||
const [code] = AbiCoder.defaultAbiCoder().decode(['uint256'], '0x' + raw.slice(10));
|
||||
const codeNum = Number(code);
|
||||
return PANIC_CODES[codeNum] ?? `Contract panic (code ${codeNum})`;
|
||||
} catch {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
|
||||
if (SELECTOR_RE.test(raw)) {
|
||||
const selector = lower.slice(0, 10);
|
||||
const name = (selectorMap as Record<string, string>)[selector];
|
||||
if (name) return formatErrorName(name);
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
Reference in New Issue
Block a user