Skip to content

Commit e4eb4aa

Browse files
committed
feat: add Hardhat 3 compatibility tests and update configurations
- Introduced HH3CompatibilityTest to ensure compatibility with Hardhat 3's artifact structure. - Added script for setting up test environment for HH3 compatibility. - Updated foundry.toml to include new profile for HH3 compatibility. - Enhanced package.json scripts to facilitate HH3 testing. - Created Greeter.json artifact for testing purposes. - Refactored file structure to align with Hardhat's output directory.
1 parent 452ab57 commit e4eb4aa

File tree

7 files changed

+826
-108
lines changed

7 files changed

+826
-108
lines changed

foundry.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"lib/forge-std": {
3+
"rev": "b93cf4bc34ff214c099dc970b153f85ade8c9f66"
4+
}
5+
}

foundry.toml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ out = "out"
44
libs = ["node_modules", "lib"]
55
build_info = true
66
extra_output = ["storageLayout"]
7+
fs_permissions = [
8+
{ access = "read", path = "out" },
9+
{ access = "read", path = "test/fixtures" },
10+
{ access = "read-write", path = "artifacts" }
11+
]
712

813
[profile.openzeppelin-contracts-v4]
914
src = "test-profiles/openzeppelin-contracts-v4/src"
@@ -35,4 +40,17 @@ test = "test-profiles/build-info-v2-bad/test"
3540

3641
[profile.build-info-v2-reference-contract]
3742
src = "test-profiles/build-info-v2-reference-contract/src"
38-
test = "test-profiles/build-info-v2-reference-contract/test"
43+
test = "test-profiles/build-info-v2-reference-contract/test"
44+
45+
[profile.hh3-compatibility]
46+
src = "src"
47+
out = "artifacts/contracts"
48+
libs = ["node_modules", "lib"]
49+
build_info = true
50+
extra_output = ["storageLayout"]
51+
fs_permissions = [
52+
{ access = "read", path = "test/fixtures" },
53+
{ access = "read-write", path = "artifacts" },
54+
{ access = "read", path = "out" }
55+
]
56+
ffi = true

package.json

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,53 @@
1-
{
2-
"name": "@openzeppelin/foundry-upgrades",
3-
"version": "0.4.0",
4-
"description": "Foundry library for deploying and managing upgradeable contracts",
5-
"license": "MIT",
6-
"files": [
7-
"src/**/*"
8-
],
9-
"repository": {
10-
"type": "git",
11-
"url": "https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades.git"
12-
},
13-
"scripts": {
14-
"clean": "forge clean && hardhat clean",
15-
"compile": "forge build",
16-
"test": "npm run forge:test && npm run forge:script && npm run forge:test-v4 && npm run forge:script-v4 && npm run forge:test-v4-with-v5-proxies && npm run forge:script-v4-with-v5-proxies && npm run test-reference-builds",
17-
"forge:test": "FOUNDRY_PROFILE=default forge test -vvv --ffi --force",
18-
"forge:script": "FOUNDRY_PROFILE=default forge script test/Upgrades.s.sol --ffi --force",
19-
"forge:test-v4": "FOUNDRY_PROFILE=openzeppelin-contracts-v4 forge test -vvv --ffi --force --use solc:0.8.2",
20-
"forge:script-v4": "FOUNDRY_PROFILE=openzeppelin-contracts-v4 forge script test-profiles/openzeppelin-contracts-v4/test/LegacyUpgrades.s.sol --ffi --force --use solc:0.8.2",
21-
"forge:test-v4-with-v5-proxies": "FOUNDRY_PROFILE=openzeppelin-contracts-v4-with-v5-proxies forge test -vvv --ffi --force",
22-
"forge:script-v4-with-v5-proxies": "FOUNDRY_PROFILE=openzeppelin-contracts-v4-with-v5-proxies forge script test-profiles/openzeppelin-contracts-v4-with-v5-proxies/test/Upgrades.s.sol --ffi --force",
23-
"test-reference-builds": "bash scripts/test-reference-builds.sh",
24-
"lint": "prettier --log-level warn --ignore-path .gitignore '{src,test}/**/*.sol' --check && solhint 'src/**/*.sol'",
25-
"lint:fix": "prettier --log-level warn --ignore-path .gitignore '{src,test}/**/*.sol' --write",
26-
"docgen": "hardhat clean && hardhat compile && hardhat docgen",
27-
"docgen:test": "yarn docgen && git diff --exit-code docs/modules/api/pages",
28-
"version-package": "bash scripts/release/version.sh",
29-
"publish-package": "bash scripts/release/publish.sh"
30-
},
31-
"devDependencies": {
32-
"@nomicfoundation/hardhat-foundry": "^1.1.1",
33-
"@openzeppelin/contracts": "^5.0.2",
34-
"@openzeppelin/contracts-upgradeable": "^5.0.2",
35-
"@openzeppelin/contracts-v4": "npm:@openzeppelin/contracts@^v4.9.6",
36-
"@openzeppelin/contracts-upgradeable-v4": "npm:@openzeppelin/contracts-upgradeable@^v4.9.6",
37-
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.10",
38-
"@openzeppelin/upgrades-core": "^1.37.0",
39-
"hardhat": "^2.21.0",
40-
"prettier": "^3.0.0",
41-
"prettier-plugin-solidity": "^1.1.0",
42-
"solhint": "^3.3.6",
43-
"solhint-plugin-openzeppelin": "file:scripts/solhint-custom",
44-
"solidity-docgen": "^0.6.0-beta.36",
45-
"@changesets/cli": "^2.29.3",
46-
"@changesets/changelog-github": "^0.5.1"
47-
},
48-
"peerDependencies": {
49-
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.10",
50-
"@openzeppelin/upgrades-core": "^1.37.0"
1+
{
2+
"name": "@openzeppelin/foundry-upgrades",
3+
"version": "0.4.0",
4+
"description": "Foundry library for deploying and managing upgradeable contracts",
5+
"license": "MIT",
6+
"files": [
7+
"src/**/*"
8+
],
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades.git"
12+
},
13+
"scripts": {
14+
"clean": "forge clean && hardhat clean",
15+
"compile": "forge build",
16+
"test": "npm run forge:test && npm run forge:test:hh3 && npm run forge:script && npm run forge:test-v4 && npm run forge:script-v4 && npm run forge:test-v4-with-v5-proxies && npm run forge:script-v4-with-v5-proxies && npm run test-reference-builds",
17+
"forge:test": "FOUNDRY_OUT=out FOUNDRY_PROFILE=default forge test --no-match-contract HH3CompatibilityTest -vvv --ffi --force",
18+
"forge:test:hh3": "./scripts/test-hh3-compatibility.sh",
19+
"forge:script": "FOUNDRY_PROFILE=default forge script test/Upgrades.s.sol --ffi --force",
20+
"forge:test-v4": "FOUNDRY_PROFILE=openzeppelin-contracts-v4 forge test -vvv --ffi --force --use solc:0.8.2",
21+
"forge:script-v4": "FOUNDRY_PROFILE=openzeppelin-contracts-v4 forge script test-profiles/openzeppelin-contracts-v4/test/LegacyUpgrades.s.sol --ffi --force --use solc:0.8.2",
22+
"forge:test-v4-with-v5-proxies": "FOUNDRY_PROFILE=openzeppelin-contracts-v4-with-v5-proxies forge test -vvv --ffi --force",
23+
"forge:script-v4-with-v5-proxies": "FOUNDRY_PROFILE=openzeppelin-contracts-v4-with-v5-proxies forge script test-profiles/openzeppelin-contracts-v4-with-v5-proxies/test/Upgrades.s.sol --ffi --force",
24+
"test-reference-builds": "bash scripts/test-reference-builds.sh",
25+
"lint": "prettier --log-level warn --ignore-path .gitignore '{src,test}/**/*.sol' --check && solhint 'src/**/*.sol'",
26+
"lint:fix": "prettier --log-level warn --ignore-path .gitignore '{src,test}/**/*.sol' --write",
27+
"docgen": "hardhat clean && hardhat compile && hardhat docgen",
28+
"docgen:test": "yarn docgen && git diff --exit-code docs/modules/api/pages",
29+
"version-package": "bash scripts/release/version.sh",
30+
"publish-package": "bash scripts/release/publish.sh"
31+
},
32+
"devDependencies": {
33+
"@nomicfoundation/hardhat-foundry": "^1.1.1",
34+
"@openzeppelin/contracts": "^5.0.2",
35+
"@openzeppelin/contracts-upgradeable": "^5.0.2",
36+
"@openzeppelin/contracts-v4": "npm:@openzeppelin/contracts@^v4.9.6",
37+
"@openzeppelin/contracts-upgradeable-v4": "npm:@openzeppelin/contracts-upgradeable@^v4.9.6",
38+
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.10",
39+
"@openzeppelin/upgrades-core": "^1.37.0",
40+
"hardhat": "^2.21.0",
41+
"prettier": "^3.0.0",
42+
"prettier-plugin-solidity": "^1.1.0",
43+
"solhint": "^3.3.6",
44+
"solhint-plugin-openzeppelin": "file:scripts/solhint-custom",
45+
"solidity-docgen": "^0.6.0-beta.36",
46+
"@changesets/cli": "^2.29.3",
47+
"@changesets/changelog-github": "^0.5.1"
48+
},
49+
"peerDependencies": {
50+
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.10",
51+
"@openzeppelin/upgrades-core": "^1.37.0"
52+
}
5153
}
52-
}

scripts/test-hh3-compatibility.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
# scripts/test-hh3-compatibility.sh
3+
# Script para rodar o teste de compatibilidade HH3
4+
5+
set -e
6+
7+
mkdir -p artifacts/contracts/test/contracts/Greeter.sol
8+
cp test/fixtures/hh3-artifacts/contracts/test/contracts/Greeter.sol/Greeter.json \
9+
artifacts/contracts/test/contracts/Greeter.sol/Greeter.json
10+
11+
export FOUNDRY_OUT=artifacts/contracts
12+
forge test --match-contract HH3CompatibilityTest -vvv --ffi --force

test/HH3Compatibility.t.sol

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
import {Test} from "forge-std/Test.sol";
5+
6+
import {Utils, ContractInfo} from "openzeppelin-foundry-upgrades/internal/Utils.sol";
7+
8+
import {Greeter} from "./contracts/Greeter.sol";
9+
10+
/**
11+
* @dev Tests to ensure compatibility with Hardhat 3 environment.
12+
*
13+
* Hardhat 3 uses:
14+
* - artifacts/contracts/ as the output directory (instead of out/)
15+
* - artifacts/build-info/ for build info files
16+
* - FOUNDRY_OUT environment variable should point to artifacts/contracts
17+
*
18+
* This test ensures that the foundry-upgrades library works correctly
19+
* when FOUNDRY_OUT is set to match Hardhat's structure.
20+
*
21+
* NOTE: This test MUST be run via scripts/test-hh3-compatibility.sh
22+
* which sets up the HH3 artifacts in the correct location.
23+
*/
24+
contract HH3CompatibilityTest is Test {
25+
string constant HH3_OUT_DIR = "artifacts/contracts";
26+
string constant DEFAULT_OUT_DIR = "out";
27+
28+
/**
29+
* @dev Test that Utils.getOutDir() respects FOUNDRY_OUT environment variable.
30+
*
31+
* NOTE: FOUNDRY_OUT must be set externally via the test script.
32+
* vm.setEnv() does not work for FOUNDRY_* variables as Foundry treats them specially.
33+
*/
34+
function testGetOutDir_respectsFOUNDRY_OUT() public {
35+
string memory outDir = Utils.getOutDir();
36+
assertEq(outDir, HH3_OUT_DIR, "Utils.getOutDir() should respect FOUNDRY_OUT");
37+
}
38+
39+
/**
40+
* @dev Test that vm.envOr() fallback works correctly when variable doesn't exist.
41+
*
42+
* This validates the fallback mechanism used by Utils.getOutDir().
43+
*/
44+
function testGetOutDir_fallbackToDefault() public {
45+
string memory defaultValue = "out";
46+
string memory defaultOut = vm.envOr("FOUNDRY_OUT_NONEXISTENT", defaultValue);
47+
assertEq(defaultOut, "out");
48+
}
49+
50+
/**
51+
* @dev Test that getContractInfo works with HH3 artifact structure.
52+
*
53+
* The HH3 artifact was copied from fixtures by the script and placed
54+
* in artifacts/contracts/test/contracts/Greeter.sol/Greeter.json
55+
*/
56+
function testGetContractInfo_withHH3Structure() public {
57+
ContractInfo memory info = Utils.getContractInfo("Greeter.sol", HH3_OUT_DIR);
58+
59+
assertEq(info.shortName, "Greeter", "Contract name should be Greeter");
60+
assertEq(info.contractPath, "test/contracts/Greeter.sol", "Contract path should match");
61+
assertTrue(bytes(info.contractPath).length > 0, "Contract path should not be empty");
62+
}
63+
64+
/**
65+
* @dev Test that getContractInfo works with Foundry's default structure.
66+
*
67+
* This validates backward compatibility - the library should still work
68+
* with the standard Foundry output directory structure.
69+
*
70+
* NOTE: This test passes the outDir directly, not via Utils.getOutDir(),
71+
* because FOUNDRY_OUT is set to artifacts/contracts by the script.
72+
*/
73+
function testGetContractInfo_withFoundryStructure() public {
74+
ContractInfo memory info = Utils.getContractInfo("Greeter.sol", DEFAULT_OUT_DIR);
75+
76+
assertEq(info.shortName, "Greeter", "Contract name should be Greeter");
77+
assertEq(info.contractPath, "test/contracts/Greeter.sol", "Contract path should match");
78+
}
79+
80+
/**
81+
* @dev Test that FOUNDRY_OUT environment variable can be read via vm.envOr.
82+
*
83+
* NOTE: FOUNDRY_OUT must be set externally via the test script.
84+
* vm.setEnv() does not work for FOUNDRY_* variables.
85+
*/
86+
function testFOUNDRY_OUT_environmentVariable() public {
87+
string memory defaultValue = "out";
88+
string memory foundryOut = vm.envOr("FOUNDRY_OUT", defaultValue);
89+
assertEq(foundryOut, HH3_OUT_DIR, "FOUNDRY_OUT should be set by the test script");
90+
}
91+
}

test/HH3CompatibilityTest.sol

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)