5/5
## Compiling Your Panagram Smart Contract: A Step-by-Step Guide Before diving into writing tests for any smart contract, it's crucial to ensure it compiles correctly. This initial build step helps catch syntax errors, type mismatches, and other issues that would prevent successful deployment or lead to unexpected behavior. In this lesson, we'll walk through the process of compiling the `Panagram.sol` contract using the `forge build` command, identify common errors, and fix them. Our `Panagram.sol` contract is designed to inherit functionalities from both `ERC1155` (a multi-token standard) and `Ownable` (for access control). Let's see what happens when we try to compile it for the first time. ## Initial Compilation Attempt and Error Analysis We'll start by navigating to our project directory in the terminal. In this case, it's `zk_panagram/mac contracts %`. From here, we execute the `forge build` command, a powerful tool from the Foundry development suite used to compile Solidity projects. ```bash forge build ``` Upon execution, the compiler attempts to process our `Panagram.sol` file: ``` Compiling... [⠢] Compiling 1 files with Solc 0.8.27 [⠘] Solc 0.8.27 finished in 66.38ms Error: Compiler run failed: Error (7920): Identifier not found or not unique. --> src/Panagram.sol:8:31: | 8 | contract Panagram is ERC1155, Ownerable { | ^^^^^^^^^ ``` The output clearly indicates a compilation failure. The key message here is `Error (7920): Identifier not found or not unique.` The compiler points directly to line 8 of `src/Panagram.sol`, specifically highlighting `Ownerable`. This tells us that the Solidity compiler (Solc version 0.8.27 in this instance) doesn't recognize `Ownerable` as a valid contract, type, or library. This is a common issue, often stemming from a simple typographical error. The `Ownable` contract, typically imported from libraries like OpenZeppelin, is a standard for implementing ownership-based access control. It seems we've misspelled it. ## Correcting the First Typo: `Ownerable` to `Ownable` Let's open `Panagram.sol` and navigate to line 8. **Before correction (Line 8):** ```solidity contract Panagram is ERC1155, Ownerable { ``` We can see the typo `Ownerable`. We need to change this to `Ownable`. **After correction (Line 8):** ```solidity contract Panagram is ERC1155, Ownable { ``` With this change, we've correctly declared that our `Panagram` contract inherits from `ERC1155` and the standard `Ownable` contract. ## Proactive Debugging: Checking the Constructor When dealing with inheritance, it's good practice to also check the contract's constructor. The constructor of a child contract often needs to call the constructors of its parent contracts. Given the typo in the inheritance list, there's a high chance a similar mistake exists in the constructor when initializing `Ownable`. Let's examine the constructor of `Panagram.sol`: **Constructor Snippet (before further correction, approximate line 29):** ```solidity constructor(IVerifier _verifier) ERC1155("ipfs://bafybeicqfc4ipkle34tgqv3gh7gccwhmr22qdg7p6k6oxon255mnwb6csi/{id}.json") Owner(msg.sender) { // <--- Potential issue here s_verifier = _verifier; } ``` Indeed, we see another typo. The call `Owner(msg.sender)` is attempting to initialize a parent contract named `Owner`. However, since we are inheriting from `Ownable`, the constructor call should also be `Ownable(msg.sender)`. This initializes the `Ownable` contract, setting the deployer (`msg.sender`) as the initial owner. ## Correcting the Second Typo: `Owner` to `Ownable` in the Constructor We'll correct this second typo in the constructor. **Constructor call: Before correction:** ```solidity // ... ERC1155("ipfs://bafybeicqfc4ipkle34tgqv3gh7gccwhmr22qdg7p6k6oxon255mnwb6csi/{id}.json") Owner(msg.sender) { // ... ``` **Constructor call: After correction:** ```solidity // ... ERC1155("ipfs://bafybeicqfc4ipkle34tgqv3gh7gccwhmr22qdg7p6k6oxon255mnwb6csi/{id}.json") Ownable(msg.sender) { // Corrected from Owner to Ownable // ... ``` With both `Ownerable` corrected to `Ownable` in the inheritance list and `Owner` corrected to `Ownable` in the constructor's parent call, our contract should now align with the standard `Ownable` contract's interface. ## Re-compiling and Verifying the Fix Now, let's return to the terminal and re-run the `forge build` command: ```bash forge build ``` The output this time is: ``` Compiling... No files changed, compilation skipped ``` This message, "No files changed, compilation skipped," might seem anticlimactic. It indicates that Foundry detected no modifications to the Solidity files since the last *successful* compilation. In a typical workflow, if this were the first successful build after fixing the errors, you'd see a message indicating successful compilation. (In this specific recording scenario, a successful build had occurred off-screen after the fix but before this segment was recorded, hence this particular message). Regardless of the exact message, the absence of new error messages confirms that our `Panagram.sol` contract is now syntactically correct and compiles successfully. The compiler now recognizes `Ownable` and the associated constructor call. ## Key Takeaways from the Compilation Process This exercise highlights several important aspects of smart contract development: * **Compile Early, Compile Often:** Always build your project before writing extensive tests. This helps catch basic errors quickly. * **Understanding Compiler Errors:** The `Identifier not found` error is a common Solidity error, usually pointing to typos in contract names, variable names, function names, or missing imports. * **Inheritance and Constructors:** When a contract inherits from another (like `Ownable`), ensure the inherited contract's name is spelled correctly in both the inheritance list (`contract MyContract is ParentContract`) and in any calls to the parent's constructor within your contract's constructor (`ParentContract(arguments)`). * **Typos are Inevitable:** Even experienced developers make typos. Careful review and leveraging compiler feedback are essential for debugging. With our `Panagram.sol` contract now compiling successfully, we have a solid foundation to proceed with writing comprehensive tests.
Before diving into writing tests for any smart contract, it's crucial to ensure it compiles correctly. This initial build step helps catch syntax errors, type mismatches, and other issues that would prevent successful deployment or lead to unexpected behavior. In this lesson, we'll walk through the process of compiling the Panagram.sol
contract using the forge build
command, identify common errors, and fix them.
Our Panagram.sol
contract is designed to inherit functionalities from both ERC1155
(a multi-token standard) and Ownable
(for access control). Let's see what happens when we try to compile it for the first time.
We'll start by navigating to our project directory in the terminal. In this case, it's zk_panagram/mac contracts %
. From here, we execute the forge build
command, a powerful tool from the Foundry development suite used to compile Solidity projects.
Upon execution, the compiler attempts to process our Panagram.sol
file:
The output clearly indicates a compilation failure. The key message here is Error (7920): Identifier not found or not unique.
The compiler points directly to line 8 of src/Panagram.sol
, specifically highlighting Ownerable
. This tells us that the Solidity compiler (Solc version 0.8.27 in this instance) doesn't recognize Ownerable
as a valid contract, type, or library.
This is a common issue, often stemming from a simple typographical error. The Ownable
contract, typically imported from libraries like OpenZeppelin, is a standard for implementing ownership-based access control. It seems we've misspelled it.
Ownerable
to Ownable
Let's open Panagram.sol
and navigate to line 8.
Before correction (Line 8):
We can see the typo Ownerable
. We need to change this to Ownable
.
After correction (Line 8):
With this change, we've correctly declared that our Panagram
contract inherits from ERC1155
and the standard Ownable
contract.
When dealing with inheritance, it's good practice to also check the contract's constructor. The constructor of a child contract often needs to call the constructors of its parent contracts. Given the typo in the inheritance list, there's a high chance a similar mistake exists in the constructor when initializing Ownable
.
Let's examine the constructor of Panagram.sol
:
Constructor Snippet (before further correction, approximate line 29):
Indeed, we see another typo. The call Owner(msg.sender)
is attempting to initialize a parent contract named Owner
. However, since we are inheriting from Ownable
, the constructor call should also be Ownable(msg.sender)
. This initializes the Ownable
contract, setting the deployer (msg.sender
) as the initial owner.
Owner
to Ownable
in the ConstructorWe'll correct this second typo in the constructor.
Constructor call: Before correction:
Constructor call: After correction:
With both Ownerable
corrected to Ownable
in the inheritance list and Owner
corrected to Ownable
in the constructor's parent call, our contract should now align with the standard Ownable
contract's interface.
Now, let's return to the terminal and re-run the forge build
command:
The output this time is:
This message, "No files changed, compilation skipped," might seem anticlimactic. It indicates that Foundry detected no modifications to the Solidity files since the last successful compilation. In a typical workflow, if this were the first successful build after fixing the errors, you'd see a message indicating successful compilation. (In this specific recording scenario, a successful build had occurred off-screen after the fix but before this segment was recorded, hence this particular message).
Regardless of the exact message, the absence of new error messages confirms that our Panagram.sol
contract is now syntactically correct and compiles successfully. The compiler now recognizes Ownable
and the associated constructor call.
This exercise highlights several important aspects of smart contract development:
Compile Early, Compile Often: Always build your project before writing extensive tests. This helps catch basic errors quickly.
Understanding Compiler Errors: The Identifier not found
error is a common Solidity error, usually pointing to typos in contract names, variable names, function names, or missing imports.
Inheritance and Constructors: When a contract inherits from another (like Ownable
), ensure the inherited contract's name is spelled correctly in both the inheritance list (contract MyContract is ParentContract
) and in any calls to the parent's constructor within your contract's constructor (ParentContract(arguments)
).
Typos are Inevitable: Even experienced developers make typos. Careful review and leveraging compiler feedback are essential for debugging.
With our Panagram.sol
contract now compiling successfully, we have a solid foundation to proceed with writing comprehensive tests.
A foundational lesson to Compiling Your Panagram Smart Contract: A Step-by-Step Guide - Establish a solid base by compiling your `Panagram.sol` contract with `forge build`, rectifying initial errors before you begin testing. This guide details how to identify and correct common mistakes, such as typos in `Ownable` inheritance and constructor calls.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Noir syntax
Create a witness, a proof, and Solidity verifier contracts
Use the Poseidon commitment scheme
Create ZK circuits and build a full ZK protocol
ZK Merkle trees and hashing in Noir
Verify signatures without revealing the signer
Build the backend for a full-stack ZK application with noir.js and bb.js
How to create proofs and verify them in a front-end
Last updated on June 12, 2025
Duration: 6min
Duration: 1h 11min
Duration: 2h 12min
Duration: 3h 19min
Course Overview
About the course
Noir syntax
Create a witness, a proof, and Solidity verifier contracts
Use the Poseidon commitment scheme
Create ZK circuits and build a full ZK protocol
ZK Merkle trees and hashing in Noir
Verify signatures without revealing the signer
Build the backend for a full-stack ZK application with noir.js and bb.js
How to create proofs and verify them in a front-end
Last updated on June 12, 2025