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

Avoid duplicate file level functions and variables in namespace rewrite #918

Merged
merged 22 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Fix Hardhat compile errors when contracts have overloaded functions or standalone NatSpec documentation. ([#918](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/918))

## 1.31.2 (2023-11-28)

- Fix `upgradeProxy` in Hardhat from an implementation that has a fallback function and is not using OpenZeppelin Contracts 5.0. ([#926](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/926))
Expand Down
55 changes: 54 additions & 1 deletion packages/core/contracts/test/NamespacedToModify.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ contract Example {
* @notice some natspec
*/
function foo4() public {}

/**
* @dev a custom error inside a contract
*/
error CustomErrorInsideContract(address a);
}

contract HasFunction {
Expand Down Expand Up @@ -89,6 +94,8 @@ library Lib {
}

contract Consumer {
bytes4 public variableFromConstant = CONSTANT_USING_SELECTOR;

function usingFreeFunction() pure public returns (bytes4) {
return FreeFunctionUsingSelector();
}
Expand All @@ -106,6 +113,34 @@ function plusTwo(uint x) pure returns (uint) {
return x + 2;
}

/**
* @notice originally orphaned natspec
*/

/**
* @dev plusThree
* @param x x
*/
function plusThree(uint x) pure returns (uint) {
return x + 3;
}

/// @notice originally orphaned natspec 2

/**
* @dev plusThree overloaded
* @param x x
* @param y y
*/
function plusThree(uint x, uint y) pure returns (uint) {
return x + y + 3;
}

function originallyNoDocumentation() pure {}

/**
* @param foo foo
*/
using {plusTwo} for uint;

contract UsingForDirectives {
Expand All @@ -114,4 +149,22 @@ contract UsingForDirectives {
function usingFor(uint x) pure public returns (uint) {
return x.plusOne() + x.plusTwo();
}
}
}

/**
* @title a
* @author a
* @inheritdoc Example
* @dev a
* @custom:a a
* @notice a
* @param a a
* @return a a
*/
enum FreeEnum { MyEnum }

/**
* @dev a custom error outside a contract
* @param example example parameter
*/
error CustomErrorOutsideContract(Example example);
6 changes: 6 additions & 0 deletions packages/core/contracts/test/NamespacedToModifyImported.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {CONSTANT_USING_SELECTOR, plusTwo, plusThree, CustomErrorOutsideContract} from "./NamespacedToModify.sol";

contract Example {}
20 changes: 11 additions & 9 deletions packages/core/src/utils/make-namespaced.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { SolcInput, SolcOutput } from '../solc-api';
import { BuildInfo } from 'hardhat/types';

test('make namespaced input', async t => {
const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModify.sol:Example');
const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
await testMakeNamespaced(origBuildInfo, t, '0.8.20');
});

Expand All @@ -35,23 +35,25 @@ async function testMakeNamespaced(
const origInput = JSON.parse(JSON.stringify(origBuildInfo.input));

const modifiedInput = makeNamespacedInput(origBuildInfo.input, origBuildInfo.output);
normalizeStateVariableNames(modifiedInput);
t.snapshot(modifiedInput);

t.deepEqual(origBuildInfo.input, origInput);
t.notDeepEqual(modifiedInput, origInput);

// Run hardhat compile on the modified input and make sure it has no errors
const modifiedOutput = await hardhatCompile(modifiedInput, solcVersion);
t.is(modifiedOutput.errors, undefined);

normalizeIdentifiers(modifiedInput);
t.snapshot(modifiedInput);

t.deepEqual(origBuildInfo.input, origInput);
t.notDeepEqual(modifiedInput, origInput);
}

function normalizeStateVariableNames(input: SolcInput): void {
function normalizeIdentifiers(input: SolcInput): void {
for (const source of Object.values(input.sources)) {
if (source.content !== undefined) {
source.content = source.content
.replace(/\$MainStorage_\d{1,6};/g, '$MainStorage_random;')
.replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random');
.replace(/\$MainStorage_\d{1,6}/g, '$MainStorage_random')
.replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random')
.replace(/\$astId_\d+_\d{1,6}/g, '$astId_id_random');
}
}
}
Expand Down
129 changes: 97 additions & 32 deletions packages/core/src/utils/make-namespaced.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,77 +45,142 @@ Generated by [AVA](https://avajs.dev).
uint256 b;␊
} SecondaryStorage $SecondaryStorage_random;␊
/// @notice some natspec
enum $astId_id_random { dummy }
/// @param a docs
enum $astId_id_random { dummy }
/// @param a docs
enum $astId_id_random { dummy }
struct MyStruct { uint b; }␊
// keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~bytes32(uint256(0xff));␊
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
/// @notice standlone natspec␊
/// @notice natspec for var
enum $astId_id_random { dummy }
// standalone doc␊
/**␊
* standlone doc block␊
*/␊
/**␊
* doc block without natspec␊
*/␊
enum $astId_id_random { dummy }␊
/**␊
* doc block with natspec␊
*␊
* @notice some natspec␊
*/␊
enum $astId_id_random { dummy }␊
/**␊
* @dev a custom error inside a contract␊
*/␊
enum $astId_id_random { dummy }␊
}␊
contract HasFunction {␊
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
}␊
contract UsingFunction is HasFunction {␊
enum $astId_id_random { dummy }
}␊
uint256 constant FreeFunctionUsingSelector = 0;
enum FreeFunctionUsingSelector { dummy }
uint256 constant CONSTANT_USING_SELECTOR = 0;
enum CONSTANT_USING_SELECTOR { dummy }
library Lib {␊
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
}␊
contract Consumer {␊
enum $astId_id_random { dummy }␊
enum $astId_id_random { dummy }␊
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
}␊
uint256 constant plusTwo = 0;␊
enum plusTwo { dummy }␊
/**␊
* @notice originally orphaned natspec␊
*/␊
/**␊
* @dev plusThree␊
* @param x x␊
*/␊
enum plusThree { dummy }␊
/// @notice originally orphaned natspec 2␊
/**␊
* @dev plusThree overloaded␊
* @param x x␊
* @param y y␊
*/␊
enum $astId_id_random { dummy }␊
enum originallyNoDocumentation { dummy }␊
/**␊
* @param foo foo␊
*/␊
enum $astId_id_random { dummy }␊
contract UsingForDirectives {␊
enum $astId_id_random { dummy }␊
enum $astId_id_random { dummy }␊
}␊
/**␊
* @title a␊
* @author a␊
* @inheritdoc Example␊
* @dev a␊
* @custom:a a␊
* @notice a␊
* @param a a␊
* @return a a␊
*/␊
enum FreeEnum { MyEnum }␊
/**␊
* @dev a custom error outside a contract␊
* @param example example parameter␊
*/␊
enum CustomErrorOutsideContract { dummy }␊
`,
},
'contracts/test/NamespacedToModifyImported.sol': {
content: `// SPDX-License-Identifier: MIT␊
pragma solidity ^0.8.20;␊
}`,
import {CONSTANT_USING_SELECTOR, plusTwo, plusThree, CustomErrorOutsideContract} from "./NamespacedToModify.sol";␊
contract Example {}␊
`,
},
},
}
Expand Down Expand Up @@ -148,12 +213,12 @@ Generated by [AVA](https://avajs.dev).
pragma solidity 0.7.6;␊
contract HasFunction {␊
enum $astId_id_random { dummy }
enum $astId_id_random { dummy }
}␊
contract UsingFunction is HasFunction {␊
enum $astId_id_random { dummy }
}␊
`,
},
Expand Down
Binary file modified packages/core/src/utils/make-namespaced.test.ts.snap
Binary file not shown.
Loading