Interacting with deployed contracts using web3 libraries like ethers.js requires having a copy of the contract ABI somewhere in your code, and keeping it up to date is a manual and error prone process. Using the thirdweb SDKs, ABIs are automatically inferred from any deployed contracts. All you need is the contract address. No ABI copy pasting, or maintenance required.
So how does it work under the hood? The answer might surprise you!
No databases, no servers - all it takes is a powerful, yet rarely discussed feature of the Solidity compiler. Let's take a closer look!
The solidity team had the incredible foresight and ingenuity to make any contract auto verifiable from its bytecode alone. No etherscan verification needed. The idea is to make the solc compiler encode some information about the contracts in the bytecode itself during the compilation process. Enough information to be able to safely auto verify any contract in a decentralized way.
When you compile a contract using any of the popular frameworks like hardhat, forge, truffle, etc, it enables the
bytecodeHash: "ipfs" compiler flag by default. It's such a powerful feature, yet so few people know about it. Let's see how it works.
The solidity compiler, solc, produces artifacts at the end of a successful compilation. Amongst these artifacts is one called contract metadata. This a standardized JSON object, containing useful information about the contract like its name, ABI, source code, formatted code comments and compiler settings.
When solc produces the compiled bytecode for a contract, it appends a few extra bytes at the end, allowing anyone to retrieve the original contract metadata that was produced when compiling this bytecode. But how?
The genius trick is taking advantage of my favorite property of IPFS and other content addressable storage solutions: knowing the address of a file before it's uploaded.
Here’s what solc does by default when compiling any solidity contract:
computes the IPFS hash of the contract metadata JSON artifact
encodes the computed IPFS hash using CBOR encoding
appends the encoded bytes at the end of the regular compiled bytecode
This means that from any deployed contract, you can:
Get the contract bytecode using the standard RPC call
Decode the data at the end of the bytecode using a CBOR decoder
Extract the IPFS hash from the decoded data
Download the original contract metadata which contains source code, ABI, etc.
Since IPFS hashes are immutable, the contract metadata encoded this way is guaranteed to be correct and unmodified. This means that all contracts are auto-verifiable by design and without needing any third party!
So where’s the catch? Why is everybody still using centralized, closed source services to verify their contracts manually? The reason is that the compiler only computes the IPFS hash and encodes it, it does not actually upload anything to IPFS! This is where the thirdweb CLI comes in.
If you didn’t know already, thirdweb’s CLI is the swiss knife of web3 development. One of my favorites commands is
npx thirdweb deploy - it takes advantage of the solc contract metadata standard and makes deploying and integrating solidity contracts simpler and safer.
Here’s what happens when you run
npx thirdweb deploy on your solidity projects:
Detect your current project framework (hardhat, forge, truffle, etc)
Compile your contracts using your own project settings
After compilation, upload your contract metadata to IPFS, making sure it matches exactly the encoded IPFS hash in the compiled bytecode
Open up a web browser to fill in constructor parameters and deploy the contract without needing to hardcode private keys
By following the solidity contract metadata standard, contracts deployed using the thirdweb CLI are not only automatically verifiable, but also usable in any web3 app without worrying about copy pasting ABIs around!
The thirdweb SDKs allow you to load any contract just by its address, and get convenient and type safe wrappers for your contracts.
const sdk = new ThirdwebSDK("goerli"); const contract = sdk.getContract("0x..."); // no ABI needed! const nfts = await contract.erc721.getAll();
Under the hood, the thirdweb SDKs:
extract the contract metadata hash from the contract bytecode
download it from IPFS, extract the ABI and cache it
generate a type safe API for the contract
This approach provides a much nicer dev experience, as well as the following advantages:
No need to embed ABIs in the source code means faster frontend startup times
Single source of truth means ABIs are always up to date
Works with any contract, on any EVM compatible chain
Since the solc contract metadata is an industry wide standard, it works with a variety of tools that also follow this standard! For example, contracts deployed with the thirdweb CLI are auto-verified on Sourcify, a decentralized contract verification service. And of course, any contract verified on Sourcify can be used with the thirdweb SDK without needing its ABI.
Powerful standards like these is what makes the web3 ecosystem magical, and this one deserves more love from the community!