Skip to content

Commit

Permalink
Defender: Improve license type handling (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericglau authored Apr 17, 2024
1 parent 8a7c35f commit 332bd33
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.2.2 (2024-04-17)

- Defender: Fix handling of license types for block explorer verification, support `licenseType` and `skipLicenseType` options. ([#43](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades/pull/43))

## 0.2.1 (2024-03-20)

- Throw helpful error message if AST not found in contract artifacts. ([#28](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades/pull/28))
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/api/pages/api-foundry-upgrades.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ struct DefenderOptions {
string relayerId;
bytes32 salt;
string upgradeApprovalProcessId;
string licenseType;
bool skipLicenseType;
}
```

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"devDependencies": {
"@nomicfoundation/hardhat-foundry": "^1.1.1",
"@openzeppelin/contracts": "^5.0.2",
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.5",
"@openzeppelin/defender-deploy-client-cli": "0.0.1-alpha.6",
"@openzeppelin/upgrades-core": "^1.32.3",
"hardhat": "^2.21.0",
"prettier": "^3.0.0",
Expand Down
13 changes: 13 additions & 0 deletions src/Options.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,17 @@ struct DefenderOptions {
* Defaults to the upgrade approval process configured for your deployment environment on Defender.
*/
string upgradeApprovalProcessId;
/**
* License type to display on block explorers for verified source code.
* See https://etherscan.io/contract-license-types for supported values and use the string found in brackets, e.g. MIT.
* If not set, infers the license type by using the SPDX license identifier from the contract's Solidity file.
* Cannot be set if `skipLicenseType` or `skipVerifySourceCode` is `true`.
*/
string licenseType;
/**
* If set to `true`, does not set the license type on block explorers for verified source code.
* Use this if your contract's license type is not supported by block explorers.
* Defaults to `false`.
*/
bool skipLicenseType;
}
59 changes: 57 additions & 2 deletions src/internal/DefenderDeploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ library DefenderDeploy {
) internal view returns (string[] memory) {
Vm vm = Vm(Utils.CHEATCODE_ADDRESS);

if (!(defenderOpts.licenseType).toSlice().empty()) {
if (defenderOpts.skipVerifySourceCode) {
revert("The `licenseType` option cannot be used when the `skipVerifySourceCode` option is `true`");
} else if (defenderOpts.skipLicenseType) {
revert("The `licenseType` option cannot be used when the `skipLicenseType` option is `true`");
}
}

string[] memory inputBuilder = new string[](255);

uint8 i = 0;
Expand All @@ -72,15 +80,19 @@ library DefenderDeploy {
inputBuilder[i++] = Strings.toString(block.chainid);
inputBuilder[i++] = "--buildInfoFile";
inputBuilder[i++] = buildInfoFile;
inputBuilder[i++] = "--licenseType";
inputBuilder[i++] = contractInfo.license;
if (constructorData.length > 0) {
inputBuilder[i++] = "--constructorBytecode";
inputBuilder[i++] = vm.toString(constructorData);
}
if (defenderOpts.skipVerifySourceCode) {
inputBuilder[i++] = "--verifySourceCode";
inputBuilder[i++] = "false";
} else if (!(defenderOpts.licenseType).toSlice().empty()) {
inputBuilder[i++] = "--licenseType";
inputBuilder[i++] = string.concat('"', defenderOpts.licenseType, '"');
} else if (!defenderOpts.skipLicenseType && !(contractInfo.license).toSlice().empty()) {
inputBuilder[i++] = "--licenseType";
inputBuilder[i++] = string.concat('"', _toLicenseType(contractInfo), '"');
}
if (!(defenderOpts.relayerId).toSlice().empty()) {
inputBuilder[i++] = "--relayerId";
Expand All @@ -100,6 +112,49 @@ library DefenderDeploy {
return inputs;
}

function _toLicenseType(ContractInfo memory contractInfo) private pure returns (string memory) {
strings.slice memory id = contractInfo.license.toSlice();
if (id.equals("UNLICENSED".toSlice())) {
return "None";
} else if (id.equals("Unlicense".toSlice())) {
return "Unlicense";
} else if (id.equals("MIT".toSlice())) {
return "MIT";
} else if (id.equals("GPL-2.0-only".toSlice()) || id.equals("GPL-2.0-or-later".toSlice())) {
return "GNU GPLv2";
} else if (id.equals("GPL-3.0-only".toSlice()) || id.equals("GPL-3.0-or-later".toSlice())) {
return "GNU GPLv3";
} else if (id.equals("LGPL-2.1-only".toSlice()) || id.equals("LGPL-2.1-or-later".toSlice())) {
return "GNU LGPLv2.1";
} else if (id.equals("LGPL-3.0-only".toSlice()) || id.equals("LGPL-3.0-or-later".toSlice())) {
return "GNU LGPLv3";
} else if (id.equals("BSD-2-Clause".toSlice())) {
return "BSD-2-Clause";
} else if (id.equals("BSD-3-Clause".toSlice())) {
return "BSD-3-Clause";
} else if (id.equals("MPL-2.0".toSlice())) {
return "MPL-2.0";
} else if (id.equals("OSL-3.0".toSlice())) {
return "OSL-3.0";
} else if (id.equals("Apache-2.0".toSlice())) {
return "Apache-2.0";
} else if (id.equals("AGPL-3.0-only".toSlice()) || id.equals("AGPL-3.0-or-later".toSlice())) {
return "GNU AGPLv3";
} else if (id.equals("BUSL-1.1".toSlice())) {
return "BSL 1.1";
} else {
revert(
string.concat(
"SPDX license identifier ",
contractInfo.license,
" in ",
contractInfo.contractPath,
" does not look like a supported license for block explorer verification. Use the `licenseType` option to specify a license type, or set the `skipLicenseType` option to `true` to skip."
)
);
}
}

function proposeUpgrade(
address proxyAddress,
address proxyAdminAddress,
Expand Down
6 changes: 4 additions & 2 deletions src/internal/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct ContractInfo {
*/
string shortName;
/**
* License identifier from the compiled artifact
* License identifier from the compiled artifact. Empty if not found.
*/
string license;
/**
Expand Down Expand Up @@ -86,7 +86,9 @@ library Utils {
);
}
info.contractPath = vm.parseJsonString(artifactJson, ".ast.absolutePath");
info.license = vm.parseJsonString(artifactJson, ".ast.license");
if (vm.keyExistsJson(artifactJson, ".ast.license")) {
info.license = vm.parseJsonString(artifactJson, ".ast.license");
}
info.sourceCodeHash = vm.parseJsonString(
artifactJson,
string.concat(".metadata.sources.['", info.contractPath, "'].keccak256")
Expand Down
2 changes: 1 addition & 1 deletion src/internal/Versions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pragma solidity ^0.8.20;
library Versions {
// TODO add a workflow to update this automatically based on package.json
string constant UPGRADES_CORE = "^1.32.3";
string constant DEFENDER_DEPLOY_CLIENT_CLI = "0.0.1-alpha.5";
string constant DEFENDER_DEPLOY_CLIENT_CLI = "0.0.1-alpha.6";
}
3 changes: 3 additions & 0 deletions test/contracts/NoLicense.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pragma solidity ^0.8.20;

contract NoLicense {}
4 changes: 4 additions & 0 deletions test/contracts/Unlicensed.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract Unlicensed {}
4 changes: 4 additions & 0 deletions test/contracts/UnrecognizedLicense.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: UnrecognizedId
pragma solidity ^0.8.20;

contract UnrecognizedLicense {}
Loading

0 comments on commit 332bd33

Please sign in to comment.