It was 2 AM. I had just deployed my first Solidity smart contract—a simple “wave at me” dApp—and was proudly calling wave() from my frontend. But nothing happened.
No wave.
No confirmation.
Just a pending transaction and a big mystery: what is actually happening when I “call” a smart contract?
If you've ever clicked "Submit" in a Web3 app and wondered what goes on behind the scenes, this post is for you.
🧠 TL;DR First (Then We Dive Deep)
When you call a smart contract:
- You create a transaction from your wallet (like MetaMask).
- That transaction is signed by you, proving it’s legitimate.
- It gets sent to the blockchain network (Ethereum, Polygon, etc).
- Nodes pick it up, run the contract logic, and validate it.
- If all goes well, it’s added to a block, and the change becomes permanent.
But the real magic? It’s what happens between those steps.
Let’s walk through it with a story.
👩💻 The Story: Alice Sends a Transaction
Say Alice wants to buy a sword in a blockchain game by calling a smart contract function:
function buySword(uint swordId) public payable {
require(msg.value >= swordPrice, "Not enough ETH");
ownerOf[swordId] = msg.sender;
}
She clicks “Buy” in the dApp UI. Here’s what happens:
🧰 Step 1: The Frontend Prepares the Payload
The app uses Ethers.js or Web3.js to encode the function and arguments into something the Ethereum Virtual Machine (EVM) understands:
contract.buySword(2, { value: ethers.utils.parseEther("0.05") });
This turns into a raw transaction object like:
{
"to": "0xContractAddress",
"data": "0xa9059cbb000000000000000000...",
"value": "0.05 ETH"
}
🔐 Step 2: Signing the Transaction
Before it can go anywhere, Alice’s wallet (MetaMask, WalletConnect, etc.) pops up and asks her to sign the transaction.
- This doesn’t encrypt it.
- It simply proves: “Yes, I want to do this.”
The private key never leaves her wallet, but the signature is added to the transaction.
🚀 Step 3: Broadcasting to the Network
Once signed, the transaction is sent to the network—usually to a full node like Infura or Alchemy, or directly to an Ethereum node if you're self-hosting.
This step is like saying:
“Hey miners or validators, here’s a new transaction! Please include it in the next block!”
🔄 Step 4: The EVM Executes the Code
When the transaction is picked up by a node (usually by a validator or miner), the Ethereum Virtual Machine (EVM):
- Loads the smart contract's bytecode.
- Locates the function via its function selector (first 4 bytes of the
datafield). - Executes the code line by line.
- Updates blockchain state if successful.
If anything fails (like a failed require), the whole transaction is reverted — no changes are made.
⛓️ Step 5: It’s Mined & Stored On-Chain
Once the transaction passes validation:
- It's included in the next block.
- That block is appended to the blockchain.
- The transaction becomes immutable history.
Anyone can verify the transaction later on block explorers like Etherscan.
🧼 Behind the Scenes (Gas, Nonces, and State)
A few more things happening under the hood:
- Gas: The fee paid to miners/validators for computation and storage.
- Nonce: A unique number to prevent replay attacks and ensure transaction order.
- State transitions: Events and changes logged to update the ledger.
Smart contracts are deterministic: if the same inputs are given, every node will compute the same result or revert.
🤖 Read vs Write: Calls That Don’t Cost Gas
If Alice just wants to read data (like checking sword ownership), no transaction is created:
const sword = await contract.getSword(2);
- No gas
- No miner
- No blockchain write
- Just a simulated EVM call against the latest state
These are called "view" functions and are free.
🎯 Summary
When you “call” a smart contract, you're not just hitting a function. You’re:
- Encoding the function and its arguments
- Signing the request
- Broadcasting it to the network
- Letting thousands of nodes simulate, verify, and agree on the outcome
- Getting it permanently recorded on the chain
That’s a lot of trustless magic behind one click.
🛠️ Want to See It in Action?
Try this:
- Write a simple contract with a public function
- Deploy it to a testnet (like Sepolia)
- Call it from your dApp with Ethers.js
- Then watch the tx on Etherscan
You’ll see exactly what happens, from pending to confirmed.
💬 Over to You
What’s the smartest (or weirdest) smart contract you’ve interacted with?
Ever had a tx fail mysteriously?
Drop your thoughts in the comments 👇
👋 Let’s Connect
- GitHub:https://github.com/amirofekiti/ Thanks for reading! If this helped you, consider hitting ❤️ and saving the post!
Top comments (3)
Really solid walkthrough — the sword-buying example makes the whole tx lifecycle click.
To answer your question: one of the more interesting contracts I've played with was an on-chain jackpot game on Ethereum. The contract handles the entire pot, entry validation, and winner selection trustlessly — no backend, no house edge manipulation. Watching msg.value accumulate and then seeing the payout execute atomically is a great aha moment for why smart contracts matter beyond DeFi.
The tricky part is on-chain randomness. Chainlink VRF solved most of it, but before that blockhash-based randomness was exploitable by miners. Projects like cryptoshot.space are interesting case studies in provably fair randomness — good rabbit hole if you want to see view vs state-changing in action.
One addition to your explainer: the estimateGas call before MetaMask shows the popup is actually a dry-run of the full contract execution. If it reverts there, the user never sees the popup. Saves wasted gas.
the site is cryptoshot.space
Some comments may only be visible to logged-in visitors. Sign in to view all comments.