XDRIPACADEMY
Sign in

Lessons·Blockchain security·10 min·Advanced

Reading a smart contract before you sign it

Most users sign contracts they have never read. The wallet shows hex. The site shows a button. The cost of "approve" is mostly invisible until it is not. Here is how to read what you are about to authorize.


The wallet popup says "approve." There is a button. You probably press it.

This is how most on-chain mistakes happen. Not through a phishing site that looks like the real one. Not through a stolen seed. Through a perfectly legitimate-looking transaction that, once signed, gives some contract permission to drain a token from the wallet whenever it likes.

The signature is not the problem. The signature is doing exactly what you told it to do. The problem is that you told it to do something you did not understand.

This lesson is about closing that gap. You will not become a security auditor in ten minutes. You will learn enough to slow down when slowing down matters, and to ask the questions that catch the worst class of mistake.

What you are actually signing

Every transaction that interacts with a smart contract carries three pieces of information:

  1. A target address. The contract you are calling.
  2. A function and its arguments. What you are asking the contract to do.
  3. An amount of native token. Optional, often zero.

Plus: a gas limit, a fee, and a few other plumbing fields that do not change what the contract does, only what it costs.

The wallet shows you all of this, but the function and arguments are usually rendered as raw bytes (hex). That is hostile to humans, on purpose, because the wallet does not know the contract. You do.

Modern wallets do better. Some decode the function name from the four-byte selector, show "approve" instead of "0x095ea7b3", and surface the arguments. That is helpful when the contract is well-known. It is not enough when the contract is new, or has been spoofed.

Key takeaway

A signed transaction is a target plus a function plus arguments plus value. The wallet shows you all four. If you cannot answer "what does this function do, with these arguments, on this contract" before you sign, you do not know what you are signing.

The single most expensive mistake: unlimited approve

Of all the on-chain transactions that have lost users money, the single highest-cost class is the token approval. Specifically, an approval with amount = uint256.max, also known as "unlimited approval."

Here is what that means in plain language. To swap one token for another on a DEX, the DEX router needs permission to move your token. So you call approve(spender = router, amount = X). The router can now move up to X of your token until you revoke. If X is uint256.max (a very, very, very large number), the router has effectively unlimited permission, forever, until you revoke.

If the router is honest, this is fine. You save gas; you do not have to re-approve every swap. If the router has a bug, gets exploited, or was a malicious lookalike, the attacker now has the keys to that token, on your wallet, forever.

The problem is not the approval. The problem is the unlimited part. Approving exactly the amount you want to swap costs slightly more gas. It also caps the blast radius if anything goes wrong. The cost is real but small. The benefit is enormous.

Watch out

Whenever a site asks you to "approve" before a swap or stake, look at the approval amount in the wallet popup. If it is some absurdly large number, the site has asked for unlimited spending rights. Most modern wallets let you edit that number before signing. Edit it. Set it to the amount you actually want to use. Yes, you will re-approve next time. That is the point.

A simple checklist for any transaction

You do not have to read every contract. You have to ask the right four questions, in order, before you sign anything that moves value.

1. Whose contract is this?

Look at the target address. Is it the official contract for the protocol you think you are using? Cross-check on the protocol's actual website (typed, not searched), or in their Discord pinned messages, or in their docs. Address poisoning works on contracts too. A lookalike contract address with the same first and last few characters is the same trick from a different angle.

2. What function is being called?

The wallet should decode this. Common ones: transfer, approve, swap, mint, burn, permit, setApprovalForAll. Each has a meaning. setApprovalForAll(operator, true) on an NFT contract means you have given that operator permission to move every NFT in this collection that you currently own or ever will own. That sentence should make you sit up.

3. What are the arguments?

The dangerous arguments are amounts and addresses. How much of what are you giving permission to whom. If the amount is unlimited, see the warning above. If the recipient address is unfamiliar, check it. If you are calling permit or permit2, you are pre-signing a permission that someone else will broadcast on your behalf later, which has its own failure modes.

4. What does the protocol's own UI say will happen?

The site that asked you to sign should be able to tell you, in plain English, what the transaction will do. "You are swapping 100 USDC for ETH at a price of X." If the UI says one thing and the wallet popup shows something different, that is the moment to stop signing. Mismatch between UI and signature is the textbook signature of a malicious site.

If you can answer all four, sign. If you cannot, do not. That habit alone catches most of the failures.

Specific functions worth knowing by name

A few function names that should always make you read the rest of the transaction more carefully.

  • setApprovalForAll(operator, true) — Gives an operator permission to move all of your NFTs in a collection. Used by legitimate marketplaces. Also used by drainers. The line between them is whether the operator address is who you think it is.
  • permit(...) and permit2(...) — Off-chain signed approvals. You sign a message; someone else broadcasts the on-chain action later. The risk is that you signed something with a long expiry, on a token amount you did not look at, that an attacker can cash in any time before expiry.
  • multicall([...]) — A single transaction containing several sub-transactions. The wallet may show the outer wrapper but not always decode the contents. This is a place to stop and read. Multicall is fine for legitimate aggregators. It is also a way to bury one bad call inside many normal-looking ones.
  • execute(...) and execTransaction(...) — Common on smart-contract wallets and account-abstraction systems. The wrapper does not tell you what the inner action is. Read the inner data.

These are not bad in themselves. They are the functions where readers stop reading, which is exactly where attackers hide.

Tools that read the contract for you

You do not have to do this from raw hex. Several tools have made the situation a lot more tractable.

  • Wallet built-in decoders. Modern hot wallets decode the most common function calls. Use a wallet that does this; it is the cheapest defense available.
  • Transaction simulators. Services that simulate the transaction and show you what state changes would result. "Wallet X would lose Y USDC. Wallet Z would gain Y USDC." Check the simulation against your expectation. If they disagree, do not sign.
  • Block explorers with verified source. If the contract you are signing on is verified, you can read the source code. Even if you do not understand Solidity, the function name and the variable names are often enough to flag obvious problems.
  • Audit-trail tools for institutional users. If you are operating at scale, audit-trail tooling captures every transaction you sign and the state changes it produced. Useful both for compliance and for detecting compromise after the fact.

The hardware-wallet screen is a special case. When you sign with a hardware wallet, the device's own screen shows you the destination and the amount. That screen is not running on your computer; malware on the laptop cannot edit it. If the screen on the device shows something different from what the website said, the website (or your computer) is lying. The device is usually right.

The mental model

Think of every transaction as a contract you are signing in a foreign language. You do not need to learn the language. You need to insist on a faithful translation before you sign. The translation is "what does this function do, on this contract, with these arguments, and what state changes will result?"

Some sites give you a great translation. Some do not. Some want you to skip the translation. The discipline is to never sign without one, regardless of how trusted the site is or how routine the action looks.

Key takeaway

Read the four things: target, function, arguments, value. Treat unlimited approvals as the highest-cost mistake on chain. Use a wallet that decodes calls. Use a simulator when in doubt. When the UI and the wallet disagree, stop. Most on-chain losses are from signing things people did not read. The defense is the habit of reading.

Track your progress

Create a free account to mark lessons complete and unlock pillar discounts.