DEV Community

Ali Nasirlou
Ali Nasirlou

Posted on

3 Things I Learned Building a Smart Contract Project with Foundry

When I started building my NFT marketplace in Solidity, my main goal was simple:

Make it work.

But as the project grew, I realized that writing Solidity code that works is only part of the job.

Here are three things I learned while building the project with Solidity, Foundry, and OpenZeppelin.

1. Working code doesn't mean secure code

A function can work perfectly and still be vulnerable.

For example, a marketplace purchase function may look simple:

function buy(uint256 listingId) external payable {
    Listing storage listing = listings[listingId];

    require(msg.value == listing.price);

    // Transfer NFT
    // Transfer payment
    // Update listing
}
Enter fullscreen mode Exit fullscreen mode

But then you have to ask:

What if the listing was already purchased?
What if the seller no longer owns the NFT?
What if approval was revoked?
What happens during an external call?
Can the function be reentered?

This changed the way I approach smart contracts.

I don't just ask:

"Does this function work?"

I also ask:

"How could someone break it?"

2. Architecture becomes important very quickly

At the beginning, putting everything into one contract seems fine.

But an NFT marketplace can eventually include:

Listings
Purchases
Offers
Auctions
Rentals
Fees
Administration
Queries

Putting all of this into one huge contract quickly becomes difficult to maintain.

For my project, I started separating responsibilities into different components:

MarketCore.sol
MarketAdmin.sol
MarketValidation.sol
MarketEvents.sol
MarketErrors.sol
MarketQuery.sol
MarketplaceStorage.sol

The important lesson wasn't simply "use more contracts."

It was:

Give each part of the system a clear responsibility.

This makes the code easier to understand, test, and audit.

3. Testing shouldn't only prove that things work

With Foundry, it's easy to write tests for the happy path:

Create listing

Buy NFT

NFT transferred

But smart contract testing should go further.

I also want to know what happens when:

Wrong payment
Unauthorized caller
Invalid listing
Revoked approval
Already purchased NFT
Repeated calls
Failed external call

This is where testing starts becoming security research.

Instead of only testing:

"Can a user do this?"

I try to test:

"Can a malicious user make this behave differently than intended?"

Final Thoughts

Building this project taught me that smart contract development isn't just about writing Solidity.

It's about thinking about:

Architecture → State → Edge cases → Testing → Security

And the biggest lesson I've learned so far is:

A smart contract isn't good just because it works. You need to understand how it behaves when someone tries to break it.

I'm continuing to improve the project and dive deeper into smart contract security and auditing.

More experiments and lessons coming soon.

Top comments (0)