Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stopAndReturnStateDiff doesn't record CREATE2 deployed bytecode in some cases #7603

Closed
2 tasks done
JuanCoRo opened this issue Apr 9, 2024 · 3 comments · Fixed by #7632
Closed
2 tasks done

stopAndReturnStateDiff doesn't record CREATE2 deployed bytecode in some cases #7603

JuanCoRo opened this issue Apr 9, 2024 · 3 comments · Fixed by #7632
Labels
T-bug Type: bug

Comments

@JuanCoRo
Copy link

JuanCoRo commented Apr 9, 2024

Component

Forge

Have you ensured that all of these are up to date?

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (14daacf 2024-04-09T00:16:23.595685880Z)

What command(s) is the bug in?

forge script

Operating System

Linux

Describe the bug

There seems to be an edge case in which stopAndReturnStateDiff won't record the deployed bytecode of CREATE2 access kinds. An AccountAccess of kind Create will be recorded, but the deployedBytecode will be 0x if the contract is deployed via CREATE2.

The first failing Foundry commit is 05d89ca01b7a3d7c19198985ea6fbe2afd2ff437, which corresponds to the merging of #7207 (cc @RPate97)

I have not found a way to minimize this example, so we'll need to use Optimism's codebase to reproduce.

Reproduction steps

  1. foundryup --commit 05d89ca01b7a3d7c19198985ea6fbe2afd2ff437 (the first failing commit)
  2. Clone Optimism's monorepo
  3. From the git root, cd packages/contracts-bedrock
  4. In scripts/Deploy.s.sol, change the stateDiff modifier to:
    modifier stateDiff() {
        vm.startStateDiffRecording();
        _;
        VmSafe.AccountAccess[] memory accesses = vm.stopAndReturnStateDiff();
        for (uint i = 0; i < accesses.length; i++) {
            if(uint(accesses[i].kind) == 4) {
                console.log('account', accesses[i].account);
                console.logBytes(accesses[i].deployedCode);
                console.log('accessor', accesses[i].accessor);
            }
        }
    }
    This is to just output the AccountAccess of kind Create recorded in the deployment process.
  5. From the contracts-bedrock folder, run forge script scripts/Deploy.s.sol:Deploy --sig runWithStateDiff\(\)
  6. In the output, we can see that every address deployed with CREATE2 has a Create Account Access with no deployed bytecode. For instance, from the logs we get that
    SuperchainConfig deployed at 0x068E44eB31e111028c41598E4535be7468674D0A
    
    See that SuperchainConfig is indeed deployed with CREATE2.
    However, if we inspect the deployedCode corresponding to the Create kind for 0x068E44eB31e111028c41598E4535be7468674D0A we see the following
      account 0x068E44eB31e111028c41598E4535be7468674D0A
      0x
      accessor 0x4e59b44847b379578588920cA78FbF26c0B4956C
    
  7. If we instead run forge script scripts/Deploy.s.sol:Deploy --sig runWithStateDiff\(\) with the previous Foundry commit (eb5d8d46e3f2b70177ef4b2ef24d50373b446faf), we'll get the following output:
    account 0x068E44eB31e111028c41598E4535be7468674D0A
    0x608060405234801561001057600080fd5b506004361061008...
    
    Running with the latest Foundry (14daacf 2024-04-09T00:16:23.597031217Z) also shows empty bytecode
@JuanCoRo JuanCoRo added the T-bug Type: bug label Apr 9, 2024
@mds1
Copy link
Collaborator

mds1 commented Apr 9, 2024

cc @klkvr @Evalir, looks like a bug may have been introduced by the referenced PR

@Inphi
Copy link
Contributor

Inphi commented Apr 10, 2024

I can confirm this bug affects the Optimism monorepo.

@Inphi
Copy link
Contributor

Inphi commented Apr 10, 2024

Here's a smaller reproducer:

pragma solidity ^0.8.13;

import { Test } from "forge-std/Test.sol";
import {console2 as console} from "forge-std/console2.sol";
import { VmSafe } from "forge-std/Vm.sol";

contract Counter {}

contract CounterTest is Test {
    function testRecord() public {
        vm.startBroadcast(msg.sender);
        vm.startStateDiffRecording();

        Counter c = new Counter{ salt: keccak256("ekans") }();

        VmSafe.AccountAccess[] memory accesses = vm.stopAndReturnStateDiff();
        for (uint i = 0; i < accesses.length; i++) {
            if(uint(accesses[i].kind) == 4) {
                console.log('account', accesses[i].account);
                console.logBytes(accesses[i].deployedCode);
                console.log('accessor', accesses[i].accessor);
            }
        }

        vm.stopBroadcast();
    }
}

The output is:

  account 0xd866F38afaA447a5d8Ad6852d6ADfB787C1B46a1
  0x
  accessor 0x4e59b44847b379578588920cA78FbF26c0B4956C

where 0x should be non-empty for the deployed bytecode.

It seems the CREATE2 deployed code isn't provided when vm.startBroadcast is enabled. But it shows up without broadcast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants