mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-09 04:08:01 -05:00
Add support for foundry compilation and testing (#277)
* step 1/2 * fix * setup 2/2, foundry test added * readme added * fix gitmodules * fix gitmodule * fix git module * :( * forge install: forge-std v1.9.4 * readme fix
This commit is contained in:
1
contracts/.gitignore
vendored
1
contracts/.gitignore
vendored
@@ -5,6 +5,7 @@ coverage.json
|
||||
typechain
|
||||
typechain-types
|
||||
cache
|
||||
cache_forge
|
||||
build
|
||||
.openzeppelin
|
||||
|
||||
|
||||
@@ -167,4 +167,4 @@ pnpm run test
|
||||
pnpm run test:reportgas
|
||||
|
||||
pnpm run coverage
|
||||
```
|
||||
```
|
||||
|
||||
@@ -19,4 +19,4 @@ additional_compiler_profiles = [ { name = "london", evm_version = "london" } ]
|
||||
compilation_restrictions = [
|
||||
{ paths = "./**/L2MessageService.sol", evm_version = "london" },
|
||||
{ paths = "./**/TokenBridge.sol", evm_version = "london" },
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import "@nomicfoundation/hardhat-toolbox";
|
||||
import "@nomicfoundation/hardhat-foundry";
|
||||
import "@openzeppelin/hardhat-upgrades";
|
||||
import "@nomicfoundation/hardhat-foundry";
|
||||
import * as dotenv from "dotenv";
|
||||
import "hardhat-deploy";
|
||||
import "hardhat-storage-layout";
|
||||
|
||||
211
contracts/test/foundry/LineaRollup.t.sol
Normal file
211
contracts/test/foundry/LineaRollup.t.sol
Normal file
@@ -0,0 +1,211 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0
|
||||
pragma solidity 0.8.26;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../contracts/LineaRollup.sol";
|
||||
import "../../contracts/interfaces/l1/ILineaRollup.sol";
|
||||
import "../../contracts/lib/Utils.sol";
|
||||
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
|
||||
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||
|
||||
contract LineaRollupTestHelper is LineaRollup {
|
||||
function calculateY(bytes calldata data, bytes32 dataEvaluationPoint) external pure returns (bytes32) {
|
||||
return _calculateY(data, dataEvaluationPoint);
|
||||
}
|
||||
}
|
||||
|
||||
contract LineaRollupTest is Test {
|
||||
LineaRollupTestHelper lineaRollup;
|
||||
LineaRollupTestHelper implementation;
|
||||
address operator;
|
||||
address defaultAdmin;
|
||||
address verifier;
|
||||
address nonAuthorizedAccount;
|
||||
address securityCouncil;
|
||||
address fallbackOperator;
|
||||
|
||||
bytes32 VERIFIER_SETTER_ROLE;
|
||||
bytes32 VERIFIER_UNSETTER_ROLE;
|
||||
bytes32 OPERATOR_ROLE;
|
||||
bytes32 DEFAULT_ADMIN_ROLE;
|
||||
|
||||
function setUp() public {
|
||||
operator = address(0x1);
|
||||
defaultAdmin = address(0x2);
|
||||
verifier = address(0x3);
|
||||
securityCouncil = defaultAdmin;
|
||||
fallbackOperator = address(0x4);
|
||||
nonAuthorizedAccount = address(0x5);
|
||||
|
||||
implementation = new LineaRollupTestHelper();
|
||||
|
||||
ILineaRollup.InitializationData memory initData;
|
||||
initData.initialStateRootHash = bytes32(0x0);
|
||||
initData.initialL2BlockNumber = 0;
|
||||
initData.genesisTimestamp = block.timestamp;
|
||||
initData.defaultVerifier = verifier;
|
||||
initData.rateLimitPeriodInSeconds = 86400; // 1 day
|
||||
initData.rateLimitAmountInWei = 100 ether;
|
||||
|
||||
initData.roleAddresses = new IPermissionsManager.RoleAddress[](1);
|
||||
initData.roleAddresses[0] = IPermissionsManager.RoleAddress({
|
||||
addressWithRole: operator,
|
||||
role: implementation.OPERATOR_ROLE()
|
||||
});
|
||||
|
||||
initData.pauseTypeRoles = new IPauseManager.PauseTypeRole[](0);
|
||||
initData.unpauseTypeRoles = new IPauseManager.PauseTypeRole[](0);
|
||||
initData.fallbackOperator = fallbackOperator;
|
||||
initData.defaultAdmin = defaultAdmin;
|
||||
|
||||
bytes memory initializer = abi.encodeWithSelector(
|
||||
LineaRollup.initialize.selector,
|
||||
initData
|
||||
);
|
||||
|
||||
ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initializer);
|
||||
|
||||
lineaRollup = LineaRollupTestHelper(address(proxy));
|
||||
|
||||
VERIFIER_SETTER_ROLE = lineaRollup.VERIFIER_SETTER_ROLE();
|
||||
VERIFIER_UNSETTER_ROLE = lineaRollup.VERIFIER_UNSETTER_ROLE();
|
||||
OPERATOR_ROLE = lineaRollup.OPERATOR_ROLE();
|
||||
DEFAULT_ADMIN_ROLE = lineaRollup.DEFAULT_ADMIN_ROLE();
|
||||
|
||||
assertEq(lineaRollup.hasRole(DEFAULT_ADMIN_ROLE, defaultAdmin), true, "Default admin not set");
|
||||
assertEq(lineaRollup.hasRole(OPERATOR_ROLE, operator), true, "Operator not set");
|
||||
}
|
||||
|
||||
function testSubmitDataAsCalldata() public {
|
||||
ILineaRollup.CompressedCalldataSubmission memory submission;
|
||||
submission.finalStateRootHash = keccak256(abi.encodePacked("finalStateRootHash"));
|
||||
submission.snarkHash = keccak256(abi.encodePacked("snarkHash"));
|
||||
|
||||
// Adjust compressedData to start with 0x00
|
||||
submission.compressedData = hex"00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff";
|
||||
|
||||
bytes32 dataEvaluationPoint = Utils._efficientKeccak(
|
||||
submission.snarkHash,
|
||||
keccak256(submission.compressedData)
|
||||
);
|
||||
|
||||
bytes32 dataEvaluationClaim = lineaRollup.calculateY(submission.compressedData, dataEvaluationPoint);
|
||||
|
||||
bytes32 parentShnarf = lineaRollup.GENESIS_SHNARF();
|
||||
|
||||
bytes32 expectedShnarf = keccak256(
|
||||
abi.encodePacked(
|
||||
parentShnarf,
|
||||
submission.snarkHash,
|
||||
submission.finalStateRootHash,
|
||||
dataEvaluationPoint,
|
||||
dataEvaluationClaim
|
||||
)
|
||||
);
|
||||
|
||||
vm.prank(operator);
|
||||
lineaRollup.submitDataAsCalldata(submission, parentShnarf, expectedShnarf);
|
||||
|
||||
uint256 exists = lineaRollup.blobShnarfExists(expectedShnarf);
|
||||
assertEq(exists, 1, "Blob shnarf should exist after submission");
|
||||
}
|
||||
|
||||
function testChangeVerifierNotAuthorized() public {
|
||||
address newVerifier = address(0x1234);
|
||||
|
||||
vm.prank(nonAuthorizedAccount);
|
||||
vm.expectRevert(
|
||||
abi.encodePacked(
|
||||
"AccessControl: account ",
|
||||
_toAsciiString(nonAuthorizedAccount),
|
||||
" is missing role ",
|
||||
_toHexString(VERIFIER_SETTER_ROLE)
|
||||
)
|
||||
);
|
||||
lineaRollup.setVerifierAddress(newVerifier, 2);
|
||||
}
|
||||
|
||||
function testSetVerifierAddressSuccess() public {
|
||||
vm.startPrank(defaultAdmin);
|
||||
lineaRollup.grantRole(VERIFIER_SETTER_ROLE, defaultAdmin);
|
||||
vm.stopPrank();
|
||||
|
||||
address newVerifier = address(0x1234);
|
||||
|
||||
vm.prank(defaultAdmin);
|
||||
lineaRollup.setVerifierAddress(newVerifier, 2);
|
||||
|
||||
assertEq(lineaRollup.verifiers(2), newVerifier, "Verifier address not updated");
|
||||
}
|
||||
|
||||
function testUnsetVerifierAddress() public {
|
||||
vm.startPrank(defaultAdmin);
|
||||
lineaRollup.grantRole(VERIFIER_UNSETTER_ROLE, defaultAdmin);
|
||||
|
||||
lineaRollup.grantRole(VERIFIER_SETTER_ROLE, defaultAdmin);
|
||||
|
||||
address newVerifier = address(0x1234);
|
||||
lineaRollup.setVerifierAddress(newVerifier, 0);
|
||||
vm.stopPrank();
|
||||
|
||||
vm.prank(defaultAdmin);
|
||||
lineaRollup.unsetVerifierAddress(0);
|
||||
|
||||
assertEq(lineaRollup.verifiers(0), address(0), "Verifier address not unset");
|
||||
}
|
||||
|
||||
function testUnsetVerifierNotAuthorized() public {
|
||||
vm.prank(nonAuthorizedAccount);
|
||||
vm.expectRevert(
|
||||
abi.encodePacked(
|
||||
"AccessControl: account ",
|
||||
_toAsciiString(nonAuthorizedAccount),
|
||||
" is missing role ",
|
||||
_toHexString(VERIFIER_UNSETTER_ROLE)
|
||||
)
|
||||
);
|
||||
lineaRollup.unsetVerifierAddress(0);
|
||||
}
|
||||
|
||||
// Helper function to convert address to ascii string
|
||||
function _toAsciiString(address x) internal pure returns (string memory) {
|
||||
bytes memory s = new bytes(42);
|
||||
s[0] = "0";
|
||||
s[1] = "x";
|
||||
for (uint256 i = 0; i < 20; i++) {
|
||||
uint8 b = uint8(uint256(uint160(x)) / (2**(8 * (19 - i))));
|
||||
uint8 hi = b / 16;
|
||||
uint8 lo = b - 16 * hi;
|
||||
s[2 + 2 * i] = _char(hi);
|
||||
s[3 + 2 * i] = _char(lo);
|
||||
}
|
||||
return string(s);
|
||||
}
|
||||
|
||||
// Helper function to convert byte to char
|
||||
function _char(uint8 b) internal pure returns (bytes1 c) {
|
||||
if (b < 10) {
|
||||
return bytes1(b + 0x30);
|
||||
} else {
|
||||
return bytes1(b + 0x57);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to convert bytes32 to hex string
|
||||
function _toHexString(bytes32 data) internal pure returns (string memory) {
|
||||
return _toHexString(abi.encodePacked(data));
|
||||
}
|
||||
|
||||
// Helper function to convert bytes to hex string
|
||||
function _toHexString(bytes memory data) internal pure returns (string memory) {
|
||||
bytes memory hexString = new bytes(data.length * 2 + 2);
|
||||
hexString[0] = "0";
|
||||
hexString[1] = "x";
|
||||
bytes memory hexChars = "0123456789abcdef";
|
||||
for (uint256 i = 0; i < data.length; i++) {
|
||||
hexString[2 + i * 2] = hexChars[uint8(data[i] >> 4)];
|
||||
hexString[3 + i * 2] = hexChars[uint8(data[i] & 0x0f)];
|
||||
}
|
||||
return string(hexString);
|
||||
}
|
||||
}
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -15962,7 +15962,7 @@ snapshots:
|
||||
debug: 4.3.7(supports-color@8.1.1)
|
||||
enhanced-resolve: 5.17.1
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.8.1
|
||||
is-bun-module: 1.2.1
|
||||
@@ -15975,7 +15975,7 @@ snapshots:
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@@ -15997,7 +15997,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.15.1
|
||||
is-glob: 4.0.3
|
||||
|
||||
Reference in New Issue
Block a user