zemse / hardhat-tracer

🕵️ allows you to see internal calls, events and storage operations in the console
MIT License
353 stars 36 forks source link

`DELEGATECALL` opcode inside `STATICCALL` opcode is wrong #31

Closed k06a closed 1 year ago

k06a commented 1 year ago

I observe the following trace in output:

CALL <UnknownContract>.testFunction{value: 1000000000000000000}(minReturn=900000000000000000, dex=32616003717663924870734588497613482764963232143234143659850767162302778744745)
   STATICCALL <UnknownContract>.coins(i=1) => (0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44)
      DELEGATECALL <UnknownContract>.coins(i=1)

But inside test this trace I see STATICCALL instead of DELEGATECALL:

{
  "opcode": "CALL",
  "params": {
    "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
    "to": "0x2b639cc84e1ad3aa92d4ee7d2755a6abef300d72",
    "inputData": "0xa76dfc3b0000000000000000000000000000000000000000000000000c7d713b49da0000481c010001080008ce7d650321410232b484136404911780bc32756d5d1a9fa9",
    "gasLimit": 29002080,
    "value": "0x1000000000000000000",
    "returnData": "0x000000000000000000000000000000000000000000000000e9c2cb5c49e9cf81",
    "gasUsed": 213891,
    "success": true
  },
  "children": [
    {
      "opcode": "STATICCALL",
      "params": {
        "from": "0x2b639cc84e1ad3aa92d4ee7d2755a6abef300d72",
        "to": "0x21410232b484136404911780bc32756d5d1a9fa9",
        "inputData": "0xc66106570000000000000000000000000000000000000000000000000000000000000001",
        "gasLimit": 28545429,
        "returnData": "0x0000000000000000000000001ceb5cb57c4d4e2b2433641b95dd330a33185a44",
        "gasUsed": 5672,
        "success": true
      },
      "children": [
        {
          "opcode": "STATICCALL",
          "params": {
            "from": "0x2b639cc84e1ad3aa92d4ee7d2755a6abef300d72",
            "to": "0x21410232b484136404911780bc32756d5d1a9fa9",
            "inputData": "0xc66106570000000000000000000000000000000000000000000000000000000000000001",
            "gasLimit": 28096812,
            "returnData": "0x0000000000000000000000001ceb5cb57c4d4e2b2433641b95dd330a33185a44",
            "gasUsed": 3000,
            "success": true
          },
          "children": []
        }
      ]
    },
k06a commented 1 year ago

Moreover params.from and params.to are exactly the same, which gives us no clue who made this DELEGATECALL.

k06a commented 1 year ago

Printed tree with this cool helper:

function treeForEach (element, unnest, action) {
    action(element);
    for (const item of unnest(element) || []) {
        treeForEach(item, unnest, action);
    }
    return element;
}

console.log(JSON.stringify(treeForEach(tracer.lastTrace().top, tr => tr.children, tr => { delete tr.parent })));
zemse commented 1 year ago

Closing this issue since it was fixed in the linked commit.