Repository: shazow/whatsabi (ts)

Issue:
Proxy not detected when storage slot is only in init code
We found a contract that should actually be detected as an EIP1967Proxy but autoload doesn't return any proxy resolvers:

https://etherscan.io/address/0x6f943318b05AD7c6EE596A220510A6D64B518dd8#code

The problem about this contract is that the PUSH opcode with the EIP-1967 beacon storage slot is only in the init code. Init code seems to be ignored when disassembling:

https://github.com/shazow/whatsabi/blob/4b64dd182353069670484f79ce4d631b16d335d8/src/disasm.ts#L391-L400

I ran a debugger and could see that first a EIP1967Proxy was detected, but then the program / proxies got reset due to the lines above.

Pull request description:
src/disasm.ts: Inherit init code proxies if deploy code did not find proxies


Fixes #171

Patch:
diff --git a/src/disasm.ts b/src/disasm.ts
index d49411b..541d67b 100644
--- a/src/disasm.ts
+++ b/src/disasm.ts
@@ -543,6 +543,14 @@ export function disasm(bytecode: string, config?: {onlyJumpTable: boolean}): Pro
         }
     }
 
+    if (p.init && p.proxies.length === 0 && p.init.proxies.length > 0) {
+        // If we detected a proxy in init but not in the deploy code, we're going to inherit it for now.
+        // There is a scenario where we have trouble detecting a flattened immutable EIP1967 otherwise.
+        // Hopefully we can improve this later.
+        // See: https://github.com/shazow/whatsabi/issues/171
+        p.proxies = p.init.proxies;
+    }
+
     return p;
 }
 


Test patch:
diff --git a/src/__tests__/edges.test.ts b/src/__tests__/edges.test.ts
index 818e9d1..8baec0c 100644
--- a/src/__tests__/edges.test.ts
+++ b/src/__tests__/edges.test.ts
@@ -98,6 +98,17 @@ cached_test('issue 146: duplicated events', async ({ provider, withCache }) => {
   expect(Array.from(r.eventCandidates).length).toEqual(14);
 });
 
+test('issue 171: immutable EIP1967 proxy', () => {
+  // https://github.com/shazow/whatsabi/issues/171
+  // createCode from https://etherscan.io/address/0x6f943318b05AD7c6EE596A220510A6D64B518dd8
+  const createCode = "60a06040526040516105bf3803806105bf83398101604081905261002291610387565b61002c828261003e565b506001600160a01b031660805261047e565b610047826100fe565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a28051156100f2576100ed826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e79190610447565b82610211565b505050565b6100fa610288565b5050565b806001600160a01b03163b60000361013957604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b81529051600092841691635c60da1b9160048083019260209291908290030181865afa1580156101b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d99190610447565b9050806001600160a01b03163b6000036100fa57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610130565b6060600080846001600160a01b03168460405161022e9190610462565b600060405180830381855af49150503d8060008114610269576040519150601f19603f3d011682016040523d82523d6000602084013e61026e565b606091505b50909250905061027f8583836102a9565b95945050505050565b34156102a75760405163b398979f60e01b815260040160405180910390fd5b565b6060826102be576102b982610308565b610301565b81511580156102d557506001600160a01b0384163b155b156102fe57604051639996b31560e01b81526001600160a01b0385166004820152602401610130565b50805b9392505050565b8051156103185780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811461034857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561037e578181015183820152602001610366565b50506000910152565b6000806040838503121561039a57600080fd5b6103a383610331565b60208401519092506001600160401b03808211156103c057600080fd5b818501915085601f8301126103d457600080fd5b8151818111156103e6576103e661034d565b604051601f8201601f19908116603f0116810190838211818310171561040e5761040e61034d565b8160405282815288602084870101111561042757600080fd5b610438836020830160208801610363565b80955050505050509250929050565b60006020828403121561045957600080fd5b61030182610331565b60008251610474818460208701610363565b9190910192915050565b6080516101276104986000396000601e01526101276000f3fe6080604052600a600c565b005b60186014601a565b60a0565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156079573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190609b919060c3565b905090565b3660008037600080366000845af43d6000803e80801560be573d6000f35b3d6000fd5b60006020828403121560d457600080fd5b81516001600160a01b038116811460ea57600080fd5b939250505056fea2646970667358221220ba4584e06302b35e8111d9457f4e63fa0ab53461d8999af0dbc529c45465719264736f6c6343000819003300000000000000000000000028e06ce6b25529e736d45aff7c82ef4fc6f710be000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a4fab57b8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000bdc312acd6b13f28d3a17c87a07b93d056a3236d00000000000000000000000074d9fb2b522cf886872ac333480dc4779a4bb21400000000000000000000000017e49fe369062d1eeca9564e5451021da778739b0000000000000000000000007e39183cda5af65e6a18af8c3bf0c523127f83bf000000000000000000000000604ffe37a969042c86ff0b10b2d2c4ea987d6f1d0000000000000000000000002c610e4c3c4bd4d6b76d4c7ce5e376b865c35660000000000000000000000000135dda560e946695d6f155dacafc6f1f25c1f5af000000000000000000000000bfef6e99e7dd8538ae9741d91ce27a486948aa8200000000000000000000000000000000000000000000000000000000000001400000000000000000000000004368f8f944430519f2222b0458f48ad287a83230000000000000000000000000000000000000000000000000000000000000001972656473746f6e652d6176732d6d61696e6e65742d626173650000000000000000000000000000000000000000000000000000000000000000000000";
+  const r = disasm(createCode);
+  expect(r.init).toBeDefined();
+  expect(r.init?.proxies.length).toBeGreaterThan(0);
+  expect(r.proxies.length).toBeGreaterThan(0);
+  expect(r.proxies[0].name).toEqual("EIP1967Proxy");
+});
+
 // Addresses with false positive zero selectors:
 // 0x99aa182ed0e2b6c47132e95686d2c73cdeff307f
 // 0xb1116d0a09f06d3e22a264c0c233d80e93abec10