SPDX license identifiers
Solidity 0.6.8 introduces SPDX license identifiers so developers can specify the license the contract uses. (e.g. OpenZeppelin Contracts use MIT license).
SPDX license identifiers should be added to the top of contract files. (see example in OpenZeppelin Contracts ERC20.sol)
The following identifier should be added to the top of your contract (example uses MIT license):
// SPDX-License-Identifier: MIT
The license should be from one of the following: https://spdx.org/licenses/
If the license identifier isn't included in the contract file the compiler will now show a warning.
If there are multiple license identifiers in the contract file the compiler will now show an error.
An impact of this is how we verify contracts importing other contracts. Contracts are often flattened and a single file is verified (such as on Etherscan), but one file would then contain multiple license identifiers, either the same license or a mix of licenses. So the community may need to move to verifying multiple files rather than using flattening.
Solidity Compiler
SPDX license identifiers were introducted in Solc release v0.6.8:
https://github.com/ethereum/solidity/releases/tag/v0.6.8
we introduced a recommendation to use SPDX license identifiers for all source files which are also stored in the contract metadata
Solidity documentation on SPDX license identifiers:
https://solidity.readthedocs.io/en/v0.6.8/layout-of-source-files.html?highlight=spdx#spdx-license-identifier
Compiler Warning
When compiling a contract with solc 0.6.8+ without a SPDX licence identifier gives the following warning:
$ npx oz compile
✓ Compiled contracts with solc 0.6.8 (commit.0bbfe453)
Compilation warnings:
contracts/Box.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
Verification
When verifying contracts with imports on Etherscan, often contracts are flattened into a single file. (see: How to flatten and verify a smart contract using OpenZeppelin Contracts)
Flattening contracts with SPDX license identifiers results in a file with multiple SPDX license identifiers and attempting to compile generates an error:
$ npx oz compile
✖ Compiling contracts with solc 0.6.8 (commit.0bbfe453)
Compilation errors:
contracts/FlatB.sol: ParserError: Multiple SPDX license identifiers found in source file. Use "AND" or "OR" to combine multiple licenses. Please see https://spdx.org for more information.
Verification - Single License
Where all contracts share the same license, we could manually (or potentially, if the flattener supported, the flattener could do this) strip out the duplicate SPDX license identifiers to allow verification. Otherwise we can use Solidity Multiple files format and upload each of the files. (we would need to copy all of the Solidity files to a single temporary directory to upload)
I think the preferred approach will be to verify using Solidity Multiple files format.
Verification - Multiple Licenses
Where contracts have different licenses (e.g. a contract has a non-MIT license and inherits from OpenZeppelin Contracts which has the MIT license), we can't use the flatten method. Instead we need to use Solidity Multiple files format and upload each of the files. (we would need to copy all of the Solidity files to a single temporary directory to upload)
For an example: see the following verified contract: https://rinkeby.etherscan.io/address/0x6BA8d4FfD88Ccc1c0eF61820839837B598514699#code
Note, Etherscan currently shows the license that we manually selected during verification and doesn't appear to have a Multiple/Mixed license.
I think the preferred approach will be to verify using Solidity Multiple files format.
Developers (as has always been the case) need to ensure that they don't remove or change the license of any contracts that they import or use a license in their contracts that is incompatible with contracts that they import.
OpenZeppelin Contracts
Licence identifiers have been added to OpenZeppelin Contracts and will be included in future releases of OpenZeppelin Contracts (and hence OpenZeppelin Contracts Ethereum Package): https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2234
Discussion
@frangio created the following issues to discuss and track use of the identifiers and verification:
The community may need a tool that makes multiple file verification easier, either from block explorers such as Etherscan or a tool to copy all of the contract files into a single temporary directory for easy upload.
Please add to the discussion here with your experience with using SPDX license identifiers and verification.
License text not enforced
I assumed (incorrectly) that the compiler would enforce the license text but any random text will compile as long as it has the prefix SPDX-License-Identifier
(Thanks to @PreciousChicken for the find).
// SPDX-License-Identifier: RANDOM_TEXT
pragma solidity ^0.6.0;
contract MyContract {
}
$ npx oz compile
✓ Compiled contracts with solc 0.6.11 (commit.5ef660b1)
Multiple identifiers
The following generates an error
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;
contract MyContract {
}
// SPDX-License-Identifier: Something Else
Whilst the following doesn't generate an error
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: Something Else
pragma solidity ^0.6.8;
contract MyContract {
}