CryptoCadet

How to Read the Contract That Holds Your Crypto Before Trusting It

Start at the block explorer: confirm the source is verified, then check whether the address is a proxy and who can upgrade it. List every privileged role, such as owner, pauser, minter, or blacklister, and whether a single key, a multisig, or a timelock holds it. Finally review your approvals, which let contracts move your tokens without asking again.

Why the code matters more than the interface

Tokens do not sit in a wallet app. A token balance is an entry in the token contract's storage; a deposit is a balance in a vault contract; a smart account is itself a contract. The interface shows a number. The contract decides who can change it.

Smart contract code is public, and by default cannot be changed once deployed unless it was built to be upgraded, as ethereum.org's upgrading guide explains. Both halves of that sentence matter. Public means anyone can read it. Upgradeable means what you read today may not be what runs tomorrow.

Reading it has also become cheaper for attackers. In December 2025 Anthropic reported SCONE-bench, in which ten models, given eight attempts each in a simulator, produced working exploits for 207 of 405 contracts that had been exploited in real incidents. If automated reading finds weaknesses at that rate, a holder should at least read for trust assumptions before depositing.

Step 1: confirm the address and the verified source

Get the contract address from the project's own documentation, not from a search result, a reply, or transaction history, which can be poisoned with lookalikes. Then open it on a block explorer.

A verified contract shows source code that the explorer has compiled and matched against the deployed bytecode. Unverified means the bytecode cannot be read as source without decompiling, so nobody outside the deployer can easily say what it does. For anything holding meaningful value, treat that as a reason not to proceed.

Check the compiler version and any linked libraries, and note whether the verified contract is the one holding funds or a different address the interface talks to.

Step 2: check for a proxy and find the upgrade admin

Most upgradeable contracts use a proxy: a small contract that holds the storage and forwards each call with delegatecall to a separate logic contract. Replace the logic address and every function can change, including the ones that move balances.

Explorers usually flag proxies and offer a read-as-proxy view that shows the current implementation. Under the EIP-1967 convention the implementation address sits at storage slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, which you can read directly with a tool such as Foundry's cast storage.

Then find who can call the upgrade function. A single externally owned key can replace the logic at any moment. A multisig needs several signers; check its threshold and who they are. A timelock delays upgrades by a fixed period, which gives holders a window to exit, at the cost of slower emergency fixes.

Upgradeability is not a flaw in itself. USDC on Base, for example, is deployed behind a proxy, and Circle's FiatToken design includes pause and blacklist roles. That is a known issuer trust assumption rather than a bug, and reading the contract is how you see it plainly.

Step 3: list the privileged roles

Search the source for access control: onlyOwner modifiers, role constants in an AccessControl contract, and any function gated by an address check. For each one, note what it can do and who holds it.

The functions that matter most for funds: mint, which dilutes or creates claims; pause, which freezes transfers; blacklist or freeze, which blocks specific addresses; fee setters, especially without upper bounds; sweep or withdraw functions that can move contract balances; and upgradeTo.

Then resolve each holder. A role held by a contract may be a multisig, a timelock, or another admin contract with its own owner, so follow the chain until it ends at keys. Renounced ownership on the logic contract means little if a separate proxy admin can still upgrade it.

Step 4: review approvals and the wallet's own code

An ERC-20 approval lets a spender move up to a set amount of your tokens without another signature. Many interfaces request unlimited approvals for convenience, and those stay in force until revoked. Signed permit messages create the same kind of permission without an onchain approve transaction. Review current allowances on the explorer or a revocation tool and revoke any you no longer need.

If the funds sit in a smart account, its code is part of the answer too: which modules or validators are installed, which session keys are registered and with what scope, and what recovery mechanism can replace the owner. For an agent's wallet, the key question is what the agent's key can do without the owner, and whether that scope is enforced by the account or merely assumed.

What reading cannot tell you

A read for trust assumptions does not find every bug. Logic errors, oracle dependencies, and interactions with other protocols can hide in code that looks clean. An audit report is a point-in-time review of a specific version, and an upgrade can make it stale. The security of the keys behind each role is off-chain and invisible in the source. Use these four steps to know whom you are trusting and for what, then decide how much to put at risk.

Frequently asked questions

How do I check if a smart contract is safe to hold funds in?
Confirm the address from official documentation, then check on a block explorer that the source is verified. Determine whether it is a proxy and who can upgrade it, list privileged roles such as owner, pauser, and minter and who holds them, and review your token approvals. This reveals trust assumptions; it does not guarantee the absence of bugs.
How can you tell if a contract is upgradeable?
Most explorers flag proxy contracts and offer a read-as-proxy view showing the current implementation. You can also read the EIP-1967 implementation slot directly with a tool such as Foundry's cast storage. If the contract forwards calls with delegatecall to another address, the logic can be replaced by whoever controls the upgrade function.
What is a token approval and why does it matter?
An approval is a standing permission, granted through the token contract, that lets a named spender move up to a set amount of your tokens without asking again. Unlimited approvals remain in force after the purpose is served, so a later bug or compromise in the spender can drain that token. Review and revoke allowances you no longer need.
Is USDC on Base an upgradeable contract?
Yes. USDC on Base is deployed behind a proxy, and Circle's FiatToken design includes roles that can pause transfers and blacklist addresses. That is a deliberate issuer control rather than a vulnerability, and it means holding USDC includes trusting Circle's governance of those roles. Reading the contract on an explorer shows the proxy and the role holders.