Sapphire 101: A Technical Workshop For Blockchain Devs Part 2
29-Jul-2025
Medium » Coinmonks
Continuing from Part 1 of the series where we introduced Sapphire and explored confidential transactions.
#2: Signed View Calls
This section is about impersonation and view calls. Let’s go through this step by step.
When executing a transaction, msg.sender contains the address of the caller — theone who signed the transaction or the contract address of the caller function.
For view calls, Ethereum supports impersonation. This means you can set the value of msg.sender field to arbitrary value (e.g. some third-party address) and perform read-only queries on behalf of someone else.
This is perfectly fine in Ethereum, because the contract state is public anyway and anyone can simulate any execution path.
Sapphire contract storage is confidential, it forbids impersonation: For anonymous view call:msg.sender equals address(0x0) For signed view call (aka. signed query):msg.sender equals address(signer)
Here you should mitigate memory access pattern attacks by requiring specificmsg.sender.
Make the message field in the MessageBox contract private and only allow the author of the message to retrieve it.
Try using the unwrapped signer to check whether the msg.sender is really zeroed, if view call is unsigned.
#3: Frontend
The frontend folder contains a simple Vue-based app that imports the MessageBox contract from backend.
Let’s start with building the backend.
cd frontend; pnpm dev
In the demo starter we have been working with, we use Vite to reflect any changes on-the-fly and for deployment. You can preview the frontend with:
cd frontend; pnpm dev
To sign in the frontend with this demo starter, we store the MetaMask instance into local store so that it’s not reloaded each time you open a subpage.
useEthereumStore() returns {signer, unwrappedSigner, provider, unwrappedProvider} to access all flavors of the signer or the provider respectively.
Contract address, expected chain ID etc. is read from frontend/.env* files.
In contracts.ts the wrappers for the contracts are prepared for you:
Calling uwMessageBox.message() will execute Anonymous Unencrypted View Call in the background.
Calling messageBox.message() will activate MetaMask for Signed and Encrypted View Call.
Signing the same query is cached. (This helps to reduce annoying popups.)
Based on what you’ve learned so far, try setting the message in the browser with MetaMask.
#4: Precompiles
For EVMs, the coding language in use is Solidity. So, precompiles are built-in functions that extend the EVM. Be careful here as these are complex operations that are difficult to implement efficiently.
It goes without saying that Sapphire precompiles run on Sapphire only.
We can use Testnet, but for running the (automated CI) tests each time, this is not viable (slow, gas costs).
Inspired by npx hardhat node and geth — dev, the Oasis team provides the sapphire-localnet docker image which spins up an isolated Oasis network locally:
docker run --rm -it -p8545:8545 -p8546:8546 hcr.io/oasisprotocol/sapphire-localnet
Have a question or need help? Join our Discord and head over to the #dev-central channel.
Originally published at https://dev.to on July 29, 2025.
Sapphire 101: A Technical Workshop For Blockchain Devs Part 2 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.
About Author
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc fermentum lectus eget interdum varius. Curabitur ut nibh vel velit cursus molestie. Cras sed sagittis erat. Nullam id ante hendrerit, lobortis justo ac, fermentum neque. Mauris egestas maximus tortor. Nunc non neque a quam sollicitudin facilisis. Maecenas posuere turpis arcu, vel tempor ipsum tincidunt ut.