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

Hyperchains Integration #439

Open
wants to merge 45 commits into
base: dev
Choose a base branch
from

Conversation

neotheprogramist
Copy link
Contributor

No description provided.

@tejks
Copy link

tejks commented May 3, 2024

What ❔

This PR introduces invariant tests with fuzzed inputs to test the integration of hyperchains. These tests involve depositing and withdrawing tokens through the bridgehub interface. The primary functionality is based on selecting random calls from the withdraw/deposit functions, executing the calls, and verifying how balances change after each call and if the invariants are kept.

Type of deposits:

  • depositERC20
  • depositETH

Type of withdrawals

  • withdrawETH
  • withdrawERC20

Calls such as deposit and withdraw are categorized based on the type of token used (ERC20/ETH). Additionally, deposit functions consider whether the token is base or non-base and select the appropriate call.


Changed l1 contract deployment base scripts to l1-contract-foundry scripts.

  • Minor changes have been made to these scripts so that they can be used for integration testing (mainly added getters).
  • Moved scripts with appropriate configs to test directory to avoid circular dependency.
  • RegisterHyperchain.s.sol script has been changed to read multiple hyperchains from config.

Important!!! forge-std was bump to v1.8.2

Used scripts:

  • DeployErc20.s.sol
  • DeployL1.s.sol
  • RegisterHyperchain.s.sol

address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
// Create2Factory deterministic bytecode.
// https://github.com/Arachnid/deterministic-deployment-proxy
bytes internal constant CREATE2_FACTORY_BYTECODE =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use Solidity version of create2 factory instead? This way it would be easier for us to migrate zkSync L1 tests when we would use the L1 contract codebase on L2.

Comment on lines +51 to +65
bool hasGetName = false;
for (uint256 i = 0; i < selectors.length; i++) {
if (selectors[i] == bytes4(keccak256("getName()"))) {
selectors[i] = selectors[selectors.length - 1];
hasGetName = true;
break;
}
}
if (hasGetName) {
bytes4[] memory newSelectors = new bytes4[](selectors.length - 1);
for (uint256 i = 0; i < selectors.length - 1; i++) {
newSelectors[i] = selectors[i];
}
return newSelectors;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool hasGetName = false;
for (uint256 i = 0; i < selectors.length; i++) {
if (selectors[i] == bytes4(keccak256("getName()"))) {
selectors[i] = selectors[selectors.length - 1];
hasGetName = true;
break;
}
}
if (hasGetName) {
bytes4[] memory newSelectors = new bytes4[](selectors.length - 1);
for (uint256 i = 0; i < selectors.length - 1; i++) {
newSelectors[i] = selectors[i];
}
return newSelectors;
}
for (uint256 i = 0; i < selectors.length; i++) {
if (selectors[i] == bytes4(keccak256("getName()"))) {
selectors[i] = selectors[selectors.length - 1];
// Pop the last element from the array
assembly {
mstore(selectors, sub(mload(selectors), 1))
}
break;
}
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we mirror this change to main scripts (in l1-contracts-foundry) in another pr?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can change it in this PR

return selectors;
}

function getAdminSelectors() public pure returns (bytes4[] memory) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can always use getAllSelectors over getAdminSelectors /getExecutorSelectors/getGettersSelectors/getMailboxSelectors

Copy link

@tommysr tommysr May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used it, but this function requires ffi, which has to be set explicitly in test environment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFI in test is not ideal, maybe we can find middle ground solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach uses command from foundry to inspect the contract, I don't see a way to call foundry command in testing environment without ffi.

.github/workflows/buld-release.yaml Outdated Show resolved Hide resolved
.github/workflows/build-release-manual.yaml Outdated Show resolved Hide resolved
.github/workflows/build-release.yaml Outdated Show resolved Hide resolved
@@ -77,7 +77,7 @@ contract DeployErc20Script is Script {
mint: token.mint
});
console.log("Token deployed at:", tokenAddress);
token.addr = tokenAddress;
config.tokens[i].addr = tokenAddress;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an intentional change? Why?

Copy link

@tejks tejks May 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because the token variable is just a copy and does not overwrite the config value. As a result, all token addresses were the default value (address(0)), which was visible in the deployment output configuration.

Comment on lines 103 to 104
(bool success, ) = tokenAddress.call(
abi.encodeWithSignature("mint(address,uint256)", config.deployerAddress, mint)
);
(bool success,) =
tokenAddress.call(abi.encodeWithSignature("mint(address,uint256)", config.deployerAddress, mint));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And even better to cast tokenAddress to Token type and call mint there.

l1-contracts/foundry.toml Outdated Show resolved Hide resolved
return selectors;
}

function getAdminSelectors() public pure returns (bytes4[] memory) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFI in test is not ideal, maybe we can find middle ground solution.

return selectors;
}

function getAdminSelectors() public pure returns (bytes4[] memory) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import {L1ERC20Bridge} from "contracts/bridge/L1ERC20Bridge.sol";
import {DiamondProxy} from "contracts/state-transition/chain-deps/DiamondProxy.sol";

contract DeployL1Script is Script {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we maybe import this contract directly from the repo to not copy-pasting it?

description = RegisterHyperchainsScript.HyperchainDescription({
hyperchainChainId: __chainId,
baseToken: __baseToken,
bridgehubCreateNewChainSalt: 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth to test it too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants