Repository: shazow/whatsabi (ts)

Issue:
Implementation address prefixed with 0s
I was running the proxy detection on the whole Sourcify database and found some anomalies.

One thing is that I saw some FixedProxies for which the implementation address is prefixed with 0s.

See this contract on Sepolia as an example: https://sepolia.etherscan.io/address/0x2f4eeccbe817e2b9f66e8123387aa81bae08dfec

I got this proxy resolver for it:

```
  FixedProxyResolver {
    name: 'FixedProxy',
    resolvedAddress: '0x0000000000000000000000000000000000f7a60f1c88f317f369e3d8679c6689'
  }
```

The actual address should be `0x0000000000f7a60f1c88f317f369e3d8679c6689`.


Might open more issues while I check the data :)

Pull request description:
disasm: Handle padded resolved address for FixedProxyResolver
Fixes #139

Patch:
diff --git a/src/disasm.ts b/src/disasm.ts
index 94e0398..9aa82db 100644
--- a/src/disasm.ts
+++ b/src/disasm.ts
@@ -272,7 +272,11 @@ export function disasm(bytecode: string, config?: {onlyJumpTable: boolean}): Pro
             if (isPush(code.at(-3))) {
                 // Hardcoded delegate address
                 // TODO: We can probably do more here to determine which kind? Do we care?
-                const addr = bytesToHex(code.valueAt(-3), 20);
+                const val = code.valueAt(-3);
+                const addr = bytesToHex(
+                    val.slice(val.length-20), // Might be padded with zeros
+                    20,
+                );
                 p.proxies.push(new FixedProxyResolver("HardcodedDelegateProxy", addr));
 
             } else if (


Test patch:
diff --git a/src/__tests__/auto.test.ts b/src/__tests__/auto.test.ts
index d8a2f73..a7f9b1a 100644
--- a/src/__tests__/auto.test.ts
+++ b/src/__tests__/auto.test.ts
@@ -93,5 +93,5 @@ online_test('autoload loadContractResult verified etherscan', async ({ provider,
     expect(result.contractResult?.name).toBe("TransparentUpgradeableProxy");
     expect(result.contractResult?.compilerVersion).toBe("v0.8.15+commit.e14f2714");
     expect(result.contractResult?.loaderResult?.Proxy).toBe("1");
-    expect(result.contractResult?.loaderResult?.Implementation).toBe("0x8a807d39f1d642dd8c12fe2e249fe97847f01ba0");
+    expect(result.contractResult?.loaderResult?.Implementation).toMatch(/^0x[0-9a-f]{40}$/);
 });
diff --git a/src/__tests__/loaders.test.ts b/src/__tests__/loaders.test.ts
index 5b339b2..d7c9467 100644
--- a/src/__tests__/loaders.test.ts
+++ b/src/__tests__/loaders.test.ts
@@ -120,7 +120,7 @@ describe('loaders module', () => {
     const result = await loader.getContract("0xc3d688b66703497daa19211eedff47f25384cdc3");
     expect(result.name).toEqual("TransparentUpgradeableProxy");
     expect(result.loaderResult?.Proxy).toBeTruthy();
-    expect(result.loaderResult?.Implementation).toBe("0x8a807d39f1d642dd8c12fe2e249fe97847f01ba0");
+    expect(result.loaderResult?.Implementation).toMatch(/^0x[0-9a-f]{40}$/);
   }, SLOW_ETHERSCAN_TIMEOUT)
 
   online_test('MultiABILoader_getContract', async () => {
diff --git a/src/__tests__/proxies.test.ts b/src/__tests__/proxies.test.ts
index 23fc5b1..11314ca 100644
--- a/src/__tests__/proxies.test.ts
+++ b/src/__tests__/proxies.test.ts
@@ -1,6 +1,6 @@
 import { expect, describe, test } from 'vitest';
 
-import { cached_test, online_test } from './env';
+import { cached_test, online_test, makeProvider } from './env';
 
 import { disasm } from '../disasm';
 import { addSlotOffset, readArray, joinSlot } from "../slots.js";
@@ -125,6 +125,25 @@ describe('known proxy resolving', () => {
     // FIXME: Is there one on mainnet? Seems they're all on polygon
     //online_test('SequenceWallet Proxy', async() => {
     //});
+
+    cached_test('LayerrProxy on Sepolia', async({ withCache }) => {
+        // For issue #139: https://github.com/shazow/whatsabi/issues/139
+        const provider = makeProvider("https://ethereum-sepolia-rpc.publicnode.com");
+        const address = "0x2f4eeccbe817e2b9f66e8123387aa81bae08dfec";
+        const code = await withCache(
+            `${address}_code`,
+            async () => {
+                return await provider.getCode(address)
+            },
+        );
+
+        const program = disasm(code);
+        const resolver = program.proxies[0];
+        const got = await resolver.resolve(provider, address);
+        const wantImplementation = "0x0000000000f7a60f1c88f317f369e3d8679c6689";
+
+        expect(got).toEqual(wantImplementation);
+    });
 });
 
 
diff --git a/src/__tests__/util.test.ts b/src/__tests__/util.test.ts
index ceefe21..255ab41 100644
--- a/src/__tests__/util.test.ts
+++ b/src/__tests__/util.test.ts
@@ -6,18 +6,18 @@ import { hexToBytes, bytesToHex, keccak256 } from "../utils";
 
 describe('Utils', () => {
   test.each([
-    new Uint8Array([0,1,2,3]),
-    new Uint8Array([42,69,255]),
+    new Uint8Array([0, 1, 2, 3]),
+    new Uint8Array([42, 69, 255]),
     new Uint8Array([255]),
-    new Uint8Array([255,255]),
-    new Uint8Array([0,255,0,255]),
+    new Uint8Array([255, 255]),
+    new Uint8Array([0, 255, 0, 255]),
   ])("bytesToHex %s", (bytes) => {
     expect(bytesToHex(bytes)).toStrictEqual(ethers.hexlify(bytes));
   });
 
   test("bytesToHex padding", () => {
     expect(bytesToHex(new Uint8Array([0]), 20)).toStrictEqual("0x0000000000000000000000000000000000000000");
-    expect(bytesToHex(new Uint8Array([255,255,255]), 20)).toStrictEqual("0x0000000000000000000000000000000000ffffff");
+    expect(bytesToHex(new Uint8Array([255, 255, 255]), 20)).toStrictEqual("0x0000000000000000000000000000000000ffffff");
   });
 
 
@@ -36,8 +36,8 @@ describe('Utils', () => {
     "0x00010203",
     "0xffff",
     "0xffff0000111122223333444455556666777788889999aaaabbbbccccddddeeee",
-    new Uint8Array([0,1,2,3]),
-    new Uint8Array([255,0,255,0,255,0]),
+    new Uint8Array([0, 1, 2, 3]),
+    new Uint8Array([255, 0, 255, 0, 255, 0]),
   ])("keccak256 %s", (hex) => {
     expect(keccak256(hex)).toStrictEqual(ethers.keccak256(hex));
   });