Quickstart
In this tutorial, you will build and deploy a unique dApp that requires confidentiality to work. By the end of the tutorial, you should feel comfortable setting up your Eth development environment to target Sapphire, and know how and when to use confidentiality.
The expected completion time of this tutorial is 15 minutes.
Per Consensys announcement, Oasis will no longer support Truffle as of 2023-10-05 and encourage immediate migration to Hardhat. Please see our repository for the archived Truffle tutorial and the deprecated example.
Create a Sapphire-Native dApp
Porting an existing Eth app is cool, and will provide benefits such as protection against MEV. However, starting from scratch with confidentiality in mind can unlock some really novel dApps and provide a higher level of security.
One simple-but-useful dApp that takes advantage of confidentiality is a dead person's switch that reveals a secret (let's say the encryption key to a data trove) if the operator fails to re-up before too long. Let's make it happen!
Init a new Hardhat project
We're going to use Hardhat, but Sapphire should be compatible with your dev environment of choice. Let us know if things are not as expected!
- Make & enter a new directory
npx hardhat@~2.19.2 init
then create a TypeScript project.- Add
@oasisprotocol/sapphire-hardhat
as dependency:
- npm
- pnpm
- Yarn
npm install -D @oasisprotocol/sapphire-hardhat
pnpm add -D @oasisprotocol/sapphire-hardhat
yarn add --dev @oasisprotocol/sapphire-hardhat
- Install
@nomicfoundation/hardhat-toolbox
, TypeScript and other peer dependencies required by HardHat.
Add the Sapphire Testnet to Hardhat
Open up your hardhat.config.ts
and drop in these lines.
diff --git a/hardhat.config.ts b/hardhat.config.ts
index 414e974..49c95f9 100644
--- a/hardhat.config.ts
+++ b/hardhat.config.ts
@@ -1,8 +1,19 @@
import { HardhatUserConfig } from "hardhat/config";
+import '@oasisprotocol/sapphire-hardhat';
import "@nomicfoundation/hardhat-toolbox";
const config: HardhatUserConfig = {
solidity: "0.8.17",
+ networks: {
+ 'sapphire-testnet': {
+ // This is Testnet! If you want Mainnet, add a new network config item.
+ url: "https://testnet.sapphire.oasis.io",
+ accounts: process.env.PRIVATE_KEY
+ ? [process.env.PRIVATE_KEY]
+ : [],
+ chainId: 0x5aff,
+ },
+ },
};
export default config;
By importing @oasisprotocol/sapphire-hardhat
at the top of the config file,
any network config entry corresponding to the Sapphire's chain ID will
automatically be wrapped with Sapphire specifics for encrypting and signing the
transactions.
Get some Sapphire Testnet tokens
Now for the fun part. We need to configure the Sapphire network and get some tokens. Hit up the one and only Oasis Testnet faucet and select "Sapphire". Submit the form and be on your way.
Get the Contract
This is a Sapphire tutorial and you're already a Solidity expert, so let's not
bore you with explaining the gritty details of the contract.
Start by pasting Vigil.sol into contracts/Vigil.sol
.
While you're there, also place run-vigil.ts into scripts/run-vigil.ts
.
We'll need that later.
Vigil.sol, the interesting parts
The key state variables are:
SecretMetadata[] public _metas;
bytes[] private _secrets;
_metas
is marked withpublic
visibility, so despite the state itself being encrypted and not readable directly, Solidity will generate a getter that will do the decryption for you._secrets
isprivate
and therefore truly secret; only the contract can access the data contained in this mapping.
And the methods we'll care most about are
createSecret
, which adds an entry to both_metas
and_secrets
.revealSecret
, which acts as an access-controlled getter for the data contained with_secrets
. Due to trusted execution and confidentiality, the only way that the secret will get revealed is if execution proceeds all the way to the end of the function and does not revert.
The rest of the methods are useful if you actually intended to use the contract, but they demonstrate that developing for Sapphire is essentially the same as for Ethereum. You can even write tests against the Hardhat network and use Hardhat plugins.
Run the Contract
And to wrap things up, we'll put Vigil
through its paces.
First, let's see what's actually going on.
After deploying the contract, we can create a secret, check that it's not readable, wait a bit, and then check that it has become readable. Pretty cool if you ask me!
Anyway, make it happen by running
PRIVATE_KEY="0x..." npx hardhat run scripts/run-vigil.ts --network sapphire-testnet
And if you see something like the following, you'll know you're well on the road to deploying confidential dApps on Sapphire.
Vigil deployed to: 0x74dC4879B152FDD1DDe834E9ba187b3e14f462f1
Storing a secret in 0x13125d868f5fb3cbc501466df26055ea063a90014b5ccc8dfd5164dc1dd67543
Checking the secret
failed to fetch secret: reverted: not expired
Waiting...
Checking the secret again
The secret ingredient is brussels sprouts
All done!
Congratulations, you made it through the Sapphire tutorial! If you have any questions, please check out the guide and join the discussion on the #sapphire-paratime Discord channel.
Best of luck on your future forays into confidentiality!
Visit the Sapphire ParaTime repository to download the Hardhat example of this quickstart.
If your project involves building a web frontend, we recommend that you check out the official Oasis starter files.
Are you building your dApp in languages other than TypeScript? Check out the official Oasis starter project for Go and the Oasis starter project for Python.
See also
📄️ Browser Support
Writing Sapphire dApp for browser and Metamask
📄️ ParaTime Client Node
These instructions are for setting up a ParaTime client node which only observes ParaTime activity and can submit transactions. If you want to run a ParaTime node instead, see the instructions for running a ParaTime node. Similarly, if you want to run a validator or a non-validator node instead, see the instructions for running a validator node or instructions for running a non-validator node.
📄️ Web3 Gateway
Web3 gateway for Emerald and Sapphire ParaTimes