Skip to content

Commit abdc7dc

Browse files
committed
still fixing suggestions
1 parent faf4bcd commit abdc7dc

2 files changed

Lines changed: 51 additions & 36 deletions

File tree

packages/extension/src/providers/ethereum/libs/helios-verifier.ts

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
/**
2-
* helios-verifier.ts
3-
*
4-
* Experimental light-client verification layer using Helios (@a16z/helios).
5-
* Only active on Ethereum mainnet (chainId 0x1).
6-
*/
71

82
export interface VerificationResult {
93
verified: boolean;
@@ -18,9 +12,11 @@ const DEFAULT_CONSENSUS_RPC = 'https://ethereum.operationsolarstorm.org';
1812
const CHECKPOINT_FETCH_TIMEOUT_MS = 5_000;
1913

2014
let heliosProvider: any = null;
21-
let initInProgress = false;
15+
let initPromise: Promise<void> | null = null;
16+
let syncPromise: Promise<void> | null = null;
2217
let isSynced = false;
2318
let currentExecutionRpc = '';
19+
let sessionId = 0;
2420

2521
async function fetchFreshCheckpoint(consensusRpc: string): Promise<string | undefined> {
2622
const url = `${consensusRpc.replace(/\/$/, '')}/eth/v1/beacon/headers/finalized`;
@@ -44,39 +40,50 @@ export async function initHelios(
4440
executionRpc: string,
4541
consensusRpc: string = DEFAULT_CONSENSUS_RPC,
4642
): Promise<void> {
47-
if (initInProgress) return;
43+
if (initPromise) return initPromise;
4844
if (heliosProvider && currentExecutionRpc === executionRpc) return;
49-
initInProgress = true;
45+
const session = ++sessionId;
5046
heliosProvider = null;
5147
isSynced = false;
5248
currentExecutionRpc = executionRpc;
53-
try {
54-
const checkpoint = await fetchFreshCheckpoint(consensusRpc);
55-
const { createHeliosProvider } = await import('@a16z/helios');
56-
const config: Record<string, string> = {
57-
executionRpc,
58-
consensusRpc,
59-
network: 'mainnet',
60-
};
61-
if (checkpoint) config['checkpoint'] = checkpoint;
62-
heliosProvider = await createHeliosProvider(config, 'ethereum');
63-
heliosProvider
64-
.waitSynced()
65-
.then(() => { isSynced = true; console.log('[helios-verifier] synced and ready'); })
66-
.catch((err: unknown) => { console.warn('[helios-verifier] sync failed:', err); resetHelios(); });
67-
} catch (err) {
68-
console.warn('[helios-verifier] failed to initialise:', err);
69-
heliosProvider = null;
70-
currentExecutionRpc = '';
71-
} finally {
72-
initInProgress = false;
73-
}
49+
initPromise = (async () => {
50+
try {
51+
const checkpoint = await fetchFreshCheckpoint(consensusRpc);
52+
const { createHeliosProvider } = await import('@a16z/helios');
53+
const config: Record<string, string> = {
54+
executionRpc,
55+
consensusRpc,
56+
network: 'mainnet',
57+
};
58+
if (checkpoint) config['checkpoint'] = checkpoint;
59+
const provider = await createHeliosProvider(config, 'ethereum');
60+
if (session !== sessionId) return;
61+
heliosProvider = provider;
62+
syncPromise = provider.waitSynced().then(() => {
63+
if (session === sessionId && heliosProvider === provider) {
64+
isSynced = true;
65+
console.log('[helios-verifier] synced and ready');
66+
}
67+
});
68+
await syncPromise;
69+
} catch (err) {
70+
if (session === sessionId) {
71+
console.warn('[helios-verifier] failed to initialise:', err);
72+
resetHelios();
73+
}
74+
} finally {
75+
if (session === sessionId) initPromise = null;
76+
}
77+
})();
78+
return initPromise;
7479
}
7580

7681
export function resetHelios(): void {
82+
sessionId++;
7783
heliosProvider = null;
7884
isSynced = false;
79-
initInProgress = false;
85+
initPromise = null;
86+
syncPromise = null;
8087
currentExecutionRpc = '';
8188
}
8289

@@ -95,17 +102,18 @@ export async function verifyErc20Balance(
95102
contractAddress: string,
96103
walletAddress: string,
97104
rpcBalance: string,
105+
blockTag: string,
98106
chainId: string,
99107
executionRpc: string,
100108
): Promise<VerificationResult> {
101109
if (chainId.toLowerCase() !== MAINNET_CHAIN_ID) return SKIP;
102-
if (!heliosProvider && !initInProgress) void initHelios(executionRpc);
110+
await initHelios(executionRpc);
103111
if (!isSynced || !heliosProvider) return SKIP;
104112
let heliosBalanceHex: string;
105113
try {
106114
heliosBalanceHex = (await heliosProvider.request({
107115
method: 'eth_call',
108-
params: [{ to: contractAddress, data: encodeBalanceOf(walletAddress) }, 'latest'],
116+
params: [{ to: contractAddress, data: encodeBalanceOf(walletAddress) }, blockTag],
109117
})) as string;
110118
} catch (err) {
111119
console.warn('[helios-verifier] eth_call failed:', err);
@@ -114,7 +122,12 @@ export async function verifyErc20Balance(
114122
const rpcValue = decodeUint256(rpcBalance);
115123
const heliosValue = decodeUint256(heliosBalanceHex);
116124
if (rpcValue === heliosValue) {
117-
return { verified: true, tampered: false, message: 'Balance verified by Helios light client.', provenBalance: heliosBalanceHex };
125+
return {
126+
verified: true,
127+
tampered: false,
128+
message: 'Balance verified by Helios light client.',
129+
provenBalance: heliosBalanceHex,
130+
};
118131
}
119132
console.error(`[helios-verifier] MISMATCH: RPC=${rpcValue} Helios=${heliosValue}`);
120133
return {
@@ -123,4 +136,4 @@ export async function verifyErc20Balance(
123136
message: `Your RPC provider returned ${rpcValue.toString()} but Helios proved the real balance is ${heliosValue.toString()}. Your RPC provider may be lying.`,
124137
provenBalance: heliosBalanceHex,
125138
};
126-
}
139+
}

packages/extension/src/providers/ethereum/types/erc20-token.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ export class Erc20Token extends BaseToken {
4545
});
4646

4747
if (chainId) {
48+
// blockTag is 'latest' because the web3 contract call does not expose
4849
verifyErc20Balance(
4950
this.contract,
5051
address.toLowerCase(),
5152
balance,
53+
'latest',
5254
chainId,
5355
api.node,
5456
)
@@ -64,4 +66,4 @@ export class Erc20Token extends BaseToken {
6466
public async send(): Promise<any> {
6567
throw new Error('EVM-send is not implemented here');
6668
}
67-
}
69+
}

0 commit comments

Comments
 (0)