2020-05-13 14:53:54 +00:00
|
|
|
.. _metadata:
|
|
|
|
|
2017-09-05 13:20:53 +00:00
|
|
|
#################
|
|
|
|
Contract Metadata
|
|
|
|
#################
|
|
|
|
|
|
|
|
.. index:: metadata, contract verification
|
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
The Solidity compiler automatically generates a JSON file.
|
|
|
|
The file contains two kinds of information about the compiled contract:
|
|
|
|
|
|
|
|
- How to interact with the contract: ABI, and NatSpec documentation.
|
|
|
|
- How to reproduce the compilation and verify a deployed contract:
|
|
|
|
compiler version, compiler settings, and source files used.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2019-09-06 17:11:07 +00:00
|
|
|
The compiler appends by default the IPFS hash of the metadata file to the end
|
2023-03-31 12:27:57 +00:00
|
|
|
of the runtime bytecode (not necessarily the creation bytecode) of each contract,
|
|
|
|
so that, if published, you can retrieve the file in an authenticated way without
|
|
|
|
having to resort to a centralized data provider. The other available options are
|
|
|
|
the Swarm hash and not appending the metadata hash to the bytecode. These can be
|
|
|
|
configured via the :ref:`Standard JSON Interface<compiler-api>`.
|
2019-09-06 17:11:07 +00:00
|
|
|
|
|
|
|
You have to publish the metadata file to IPFS, Swarm, or another service so
|
|
|
|
that others can access it. You create the file by using the ``solc --metadata``
|
2022-07-21 12:55:45 +00:00
|
|
|
command together with the ``--output-dir`` parameter. Without the parameter,
|
2022-08-03 14:12:11 +00:00
|
|
|
the metadata will be written to standard output.
|
|
|
|
The metadata contains IPFS and Swarm references to the source code, so you have to
|
|
|
|
upload all source files in addition to the metadata file. For IPFS, the hash contained
|
2022-07-21 12:55:45 +00:00
|
|
|
in the CID returned by ``ipfs add`` (not the direct sha2-256 hash of the file)
|
|
|
|
shall match with the one contained in the bytecode.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
|
|
|
The metadata file has the following format. The example below is presented in a
|
|
|
|
human-readable way. Properly formatted metadata should use quotes correctly,
|
2023-03-31 12:27:57 +00:00
|
|
|
reduce whitespace to a minimum, and sort the keys of all objects in alphabetical order
|
|
|
|
to arrive at a canonical formatting. Comments are not permitted and are used here only for
|
2018-08-22 10:53:39 +00:00
|
|
|
explanatory purposes.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2021-07-14 16:53:15 +00:00
|
|
|
.. code-block:: javascript
|
2017-09-05 13:20:53 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
// Required: Details about the compiler, contents are specific
|
|
|
|
// to the language.
|
2021-07-14 16:53:15 +00:00
|
|
|
"compiler": {
|
2017-09-05 13:20:53 +00:00
|
|
|
// Optional: Hash of the compiler binary which produced this output
|
2023-03-31 12:27:57 +00:00
|
|
|
"keccak256": "0x123...",
|
|
|
|
// Required for Solidity: Version of the compiler
|
|
|
|
"version": "0.8.2+commit.661d1103"
|
2017-09-05 13:20:53 +00:00
|
|
|
},
|
2023-03-31 12:27:57 +00:00
|
|
|
// Required: Source code language, basically selects a "sub-version"
|
|
|
|
// of the specification
|
|
|
|
"language": "Solidity",
|
2017-09-05 13:20:53 +00:00
|
|
|
// Required: Generated information about the contract.
|
2023-03-31 12:27:57 +00:00
|
|
|
"output": {
|
2022-08-25 13:25:39 +00:00
|
|
|
// Required: ABI definition of the contract. See "Contract ABI Specification"
|
2021-07-14 16:53:15 +00:00
|
|
|
"abi": [/* ... */],
|
2023-03-31 12:27:57 +00:00
|
|
|
// Required: NatSpec developer documentation of the contract. See https://docs.soliditylang.org/en/latest/natspec-format.html for details.
|
2022-08-25 13:25:39 +00:00
|
|
|
"devdoc": {
|
|
|
|
// Contents of the @author NatSpec field of the contract
|
|
|
|
"author": "John Doe",
|
|
|
|
// Contents of the @dev NatSpec field of the contract
|
|
|
|
"details": "Interface of the ERC20 standard as defined in the EIP. See https://eips.ethereum.org/EIPS/eip-20 for details",
|
2023-03-31 12:27:57 +00:00
|
|
|
"errors": {
|
|
|
|
"MintToZeroAddress()" : {
|
|
|
|
"details": "Cannot mint to zero address"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"events": {
|
|
|
|
"Transfer(address,address,uint256)": {
|
|
|
|
"details": "Emitted when `value` tokens are moved from one account (`from`) toanother (`to`).",
|
|
|
|
"params": {
|
|
|
|
"from": "The sender address",
|
|
|
|
"to": "The receiver address",
|
|
|
|
"value": "The token amount"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"kind": "dev",
|
2022-08-25 13:25:39 +00:00
|
|
|
"methods": {
|
|
|
|
"transfer(address,uint256)": {
|
|
|
|
// Contents of the @dev NatSpec field of the method
|
|
|
|
"details": "Returns a boolean value indicating whether the operation succeeded. Must be called by the token holder address",
|
|
|
|
// Contents of the @param NatSpec fields of the method
|
|
|
|
"params": {
|
|
|
|
"_value": "The amount tokens to be transferred",
|
|
|
|
"_to": "The receiver address"
|
2023-03-31 12:27:57 +00:00
|
|
|
},
|
2022-08-25 13:25:39 +00:00
|
|
|
// Contents of the @return NatSpec field.
|
|
|
|
"returns": {
|
|
|
|
// Return var name (here "success") if exists. "_0" as key if return var is unnamed
|
|
|
|
"success": "a boolean value indicating whether the operation succeeded"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"stateVariables": {
|
|
|
|
"owner": {
|
|
|
|
// Contents of the @dev NatSpec field of the state variable
|
|
|
|
"details": "Must be set during contract creation. Can then only be changed by the owner"
|
|
|
|
}
|
2023-03-31 12:27:57 +00:00
|
|
|
},
|
|
|
|
// Contents of the @title NatSpec field of the contract
|
|
|
|
"title": "MyERC20: an example ERC20",
|
|
|
|
"version": 1 // NatSpec version
|
2022-08-25 13:25:39 +00:00
|
|
|
},
|
2023-03-31 12:27:57 +00:00
|
|
|
// Required: NatSpec user documentation of the contract. See "NatSpec Format"
|
2022-08-25 13:25:39 +00:00
|
|
|
"userdoc": {
|
2023-03-31 12:27:57 +00:00
|
|
|
"errors": {
|
|
|
|
"ApprovalCallerNotOwnerNorApproved()": [
|
|
|
|
{
|
|
|
|
"notice": "The caller must own the token or be an approved operator."
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"events": {
|
|
|
|
"Transfer(address,address,uint256)": {
|
|
|
|
"notice": "`_value` tokens have been moved from `from` to `to`"
|
|
|
|
}
|
|
|
|
},
|
2022-08-25 13:25:39 +00:00
|
|
|
"kind": "user",
|
|
|
|
"methods": {
|
|
|
|
"transfer(address,uint256)": {
|
|
|
|
"notice": "Transfers `_value` tokens to address `_to`"
|
|
|
|
}
|
|
|
|
},
|
2023-03-31 12:27:57 +00:00
|
|
|
"version": 1 // NatSpec version
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// Required: Compiler settings. Reflects the settings in the JSON input during compilation.
|
|
|
|
// Check the documentation of standard JSON input's "settings" field
|
|
|
|
"settings": {
|
|
|
|
// Required for Solidity: File path and the name of the contract or library this
|
|
|
|
// metadata is created for.
|
|
|
|
"compilationTarget": {
|
|
|
|
"myDirectory/myFile.sol": "MyContract"
|
|
|
|
},
|
|
|
|
// Required for Solidity.
|
|
|
|
"evmVersion": "london",
|
|
|
|
// Required for Solidity: Addresses for libraries used.
|
|
|
|
"libraries": {
|
|
|
|
"MyLib": "0x123123..."
|
|
|
|
},
|
|
|
|
"metadata": {
|
|
|
|
// Reflects the setting used in the input json, defaults to "true"
|
|
|
|
"appendCBOR": true,
|
|
|
|
// Reflects the setting used in the input json, defaults to "ipfs"
|
|
|
|
"bytecodeHash": "ipfs",
|
|
|
|
// Reflects the setting used in the input json, defaults to "false"
|
|
|
|
"useLiteralContent": true
|
|
|
|
},
|
|
|
|
// Optional: Optimizer settings. The fields "enabled" and "runs" are deprecated
|
|
|
|
// and are only given for backwards-compatibility.
|
|
|
|
"optimizer": {
|
|
|
|
"details": {
|
|
|
|
"constantOptimizer": false,
|
|
|
|
"cse": false,
|
|
|
|
"deduplicate": false,
|
|
|
|
// inliner defaults to "true"
|
|
|
|
"inliner": true,
|
|
|
|
// jumpdestRemover defaults to "true"
|
|
|
|
"jumpdestRemover": true,
|
|
|
|
"orderLiterals": false,
|
|
|
|
// peephole defaults to "true"
|
|
|
|
"peephole": true,
|
|
|
|
"yul": true,
|
|
|
|
// Optional: Only present if "yul" is "true"
|
|
|
|
"yulDetails": {
|
|
|
|
"optimizerSteps": "dhfoDgvulfnTUtnIf...",
|
|
|
|
"stackAllocation": false
|
2022-08-25 13:25:39 +00:00
|
|
|
}
|
2023-03-31 12:27:57 +00:00
|
|
|
},
|
|
|
|
"enabled": true,
|
|
|
|
"runs": 500
|
|
|
|
},
|
|
|
|
// Required for Solidity: Sorted list of import remappings.
|
|
|
|
"remappings": [ ":g=/dir" ]
|
|
|
|
},
|
|
|
|
// Required: Compilation source files/source units, keys are file paths
|
|
|
|
"sources": {
|
|
|
|
"destructible": {
|
|
|
|
// Required (unless "url" is used): literal contents of the source file
|
|
|
|
"content": "contract destructible is owned { function destroy() { if (msg.sender == owner) selfdestruct(owner); } }",
|
|
|
|
// Required: keccak256 hash of the source file
|
|
|
|
"keccak256": "0x234..."
|
|
|
|
},
|
|
|
|
"myDirectory/myFile.sol": {
|
|
|
|
// Required: keccak256 hash of the source file
|
|
|
|
"keccak256": "0x123...",
|
|
|
|
// Optional: SPDX license identifier as given in the source file
|
|
|
|
"license": "MIT",
|
|
|
|
// Required (unless "content" is used, see above): Sorted URL(s)
|
|
|
|
// to the source file, protocol is more or less arbitrary, but an
|
|
|
|
// IPFS URL is recommended
|
|
|
|
"urls": [ "bzz-raw://7d7a...", "dweb:/ipfs/QmN..." ]
|
2022-08-25 13:25:39 +00:00
|
|
|
}
|
2023-03-31 12:27:57 +00:00
|
|
|
},
|
|
|
|
// Required: The version of the metadata format
|
|
|
|
"version": "1"
|
2017-09-05 13:20:53 +00:00
|
|
|
}
|
|
|
|
|
2018-09-26 16:32:16 +00:00
|
|
|
.. warning::
|
2019-09-06 17:11:07 +00:00
|
|
|
Since the bytecode of the resulting contract contains the metadata hash by default, any
|
|
|
|
change to the metadata might result in a change of the bytecode. This includes
|
2018-09-26 16:32:16 +00:00
|
|
|
changes to a filename or path, and since the metadata includes a hash of all the
|
|
|
|
sources used, a single whitespace change results in different metadata, and
|
|
|
|
different bytecode.
|
|
|
|
|
2017-09-05 13:20:53 +00:00
|
|
|
.. note::
|
2019-12-12 15:28:05 +00:00
|
|
|
The ABI definition above has no fixed order. It can change with compiler versions.
|
|
|
|
Starting from Solidity version 0.5.12, though, the array maintains a certain
|
|
|
|
order.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2019-12-16 21:25:51 +00:00
|
|
|
.. _encoding-of-the-metadata-hash-in-the-bytecode:
|
|
|
|
|
2017-09-05 13:20:53 +00:00
|
|
|
Encoding of the Metadata Hash in the Bytecode
|
|
|
|
=============================================
|
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
The compiler currently by default appends the
|
|
|
|
`IPFS hash (in CID v0) <https://docs.ipfs.tech/concepts/content-addressing/#version-0-v0>`_
|
|
|
|
of the canonical metadata file and the compiler version to the end of the bytecode.
|
|
|
|
Optionally, a Swarm hash instead of the IPFS, or an experimental flag is used.
|
|
|
|
Below are all the possible fields:
|
2021-07-14 16:52:39 +00:00
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
.. code-block:: javascript
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
{
|
|
|
|
"ipfs": "<metadata hash>",
|
|
|
|
// If "bytecodeHash" was "bzzr1" in compiler settings not "ipfs" but "bzzr1"
|
|
|
|
"bzzr1": "<metadata hash>",
|
|
|
|
// Previous versions were using "bzzr0" instead of "bzzr1"
|
|
|
|
"bzzr0": "<metadata hash>",
|
|
|
|
// If any experimental features that affect code generation are used
|
|
|
|
"experimental": true,
|
|
|
|
"solc": "<compiler version>"
|
|
|
|
}
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
Because we might support other ways to retrieve the
|
|
|
|
metadata file in the future, this information is stored
|
|
|
|
`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. The last two bytes in the bytecode
|
|
|
|
indicate the length of the CBOR encoded information. By looking at this length, the
|
|
|
|
relevant part of the bytecode can be decoded with a CBOR decoder.
|
|
|
|
|
|
|
|
Check the `Metadata Playground <https://playground.sourcify.dev/>`_ to see it in action.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2019-05-08 14:12:54 +00:00
|
|
|
Whereas release builds of solc use a 3 byte encoding of the version as shown
|
|
|
|
above (one byte each for major, minor and patch version number), prerelease builds
|
|
|
|
will instead use a complete version string including commit hash and build date.
|
|
|
|
|
2022-07-24 22:22:56 +00:00
|
|
|
The commandline flag ``--no-cbor-metadata`` can be used to skip metadata
|
|
|
|
from getting appended at the end of the deployed bytecode. Equivalently, the
|
|
|
|
boolean field ``settings.metadata.appendCBOR`` in Standard JSON input can be set to false.
|
|
|
|
|
2019-04-17 08:40:26 +00:00
|
|
|
.. note::
|
|
|
|
The CBOR mapping can also contain other keys, so it is better to fully
|
2023-03-31 12:27:57 +00:00
|
|
|
decode the data by looking at the end of the bytecode for the CBOR length,
|
|
|
|
and to use a proper CBOR parser. Do not rely on it starting with ``0xa264``
|
|
|
|
or ``0xa2 0x64 'i' 'p' 'f' 's'``.
|
2018-09-25 16:49:49 +00:00
|
|
|
|
2017-09-05 13:20:53 +00:00
|
|
|
Usage for Automatic Interface Generation and NatSpec
|
|
|
|
====================================================
|
|
|
|
|
|
|
|
The metadata is used in the following way: A component that wants to interact
|
2022-08-25 13:25:39 +00:00
|
|
|
with a contract (e.g. a wallet) retrieves the code of the contract.
|
|
|
|
It decodes the CBOR encoded section containing the IPFS/Swarm hash of the
|
|
|
|
metadata file. With that hash, the metadata file is retrieved. That file
|
2019-09-06 17:11:07 +00:00
|
|
|
is JSON-decoded into a structure like above.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
|
|
|
The component can then use the ABI to automatically generate a rudimentary
|
|
|
|
user interface for the contract.
|
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
Furthermore, the wallet can use the NatSpec user documentation to display a
|
|
|
|
human-readable confirmation message to the user whenever they interact with
|
|
|
|
the contract, together with requesting authorization for the transaction signature.
|
2017-09-05 13:20:53 +00:00
|
|
|
|
2019-02-27 03:34:33 +00:00
|
|
|
For additional information, read :doc:`Ethereum Natural Language Specification (NatSpec) format <natspec-format>`.
|
2017-12-01 19:00:44 +00:00
|
|
|
|
2017-09-05 13:20:53 +00:00
|
|
|
Usage for Source Code Verification
|
|
|
|
==================================
|
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
If pinned/published, it is possible to retrieve the metadata of the contract from IPFS/Swarm.
|
|
|
|
The metadata file also contains the URLs or the IPFS hashes of the source files, as well as
|
|
|
|
the compilation settings, i.e. everything needed to reproduce a compilation.
|
|
|
|
|
|
|
|
With this information it is then possible to verify the source code of a contract by
|
|
|
|
reproducing the compilation, and comparing the bytecode from the compilation with
|
|
|
|
the bytecode of the deployed contract.
|
|
|
|
|
|
|
|
This automatically verifies the metadata since its hash is part of the bytecode, as well
|
|
|
|
as the source codes, because their hashes are part of the metadata. Any change in the files
|
|
|
|
or settings would result in a different metadata hash. The metadata here serves
|
|
|
|
as a fingerprint of the whole compilation.
|
2019-04-29 07:14:32 +00:00
|
|
|
|
2023-03-31 12:27:57 +00:00
|
|
|
`Sourcify <https://sourcify.dev>`_ makes use of this feature for "full/perfect verification",
|
|
|
|
as well as pinning the files publicly on IPFS to be accessed with the metadata hash.
|