diff --git a/docs/dapp/sapphire/quickstart.mdx b/docs/dapp/sapphire/quickstart.mdx index 0e2c14de6c..6ee53ce9e7 100644 --- a/docs/dapp/sapphire/quickstart.mdx +++ b/docs/dapp/sapphire/quickstart.mdx @@ -7,228 +7,31 @@ import {findSidebarItem} from '@site/src/sidebarUtils';

-In this tutorial, you'll port an Eth project in under 10 minutes, and then go on -to 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. +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 30 minutes. +The expected completion time of this tutorial is 15 minutes. -## Port an Eth project +:::info Sunsetting Truffle - -:::tip - -This tutorial uses [pnpm](https://pnpm.io/installation), an efficient Node -package manager. You can just as easily use `npm` or `yarn` by replacing -`pnpm` with either of those. +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]. ::: -### Deploy to Emerald (non-confidential EVM) - -#### Get some Emerald Testnet tokens - -In order to deploy to the Emerald Testnet, we'll need some tokens. -Get those by heading to [Oasis Testnet faucet] and selecting "Emerald" as -the first dropdown. -Set the second box to the address of a burner wallet. -It'll take a few moments to receive your tokens after submitting the form. - -[Oasis Testnet faucet]: https://faucet.testnet.oasis.dev/ - - - -#### Do the Truffle Thing - -You'll want a script to run some methods on the contract. -Pop open your favorite editor and paste in this code: - -```typescript -const keccak256 = require("web3").utils.keccak256; - -const MetaCoin = artifacts.require("MetaCoin"); - -async function exerciseContract() { - const mc = await MetaCoin.deployed(); - - const tx = await mc.sendCoin(mc.address, 42); - console.log(`\nSent some coins in ${tx.tx}.`); - const t = tx.logs[0].args; - console.log(`A Transfer(${t[0]}, ${t[0]}, ${t[2].toNumber()}) was emitted.`); - - const storageSlot = await new Promise((resolve, reject) => { - const getStoragePayload = { - method: "eth_getStorageAt", - params: [ - mc.address, - keccak256( - "0x" + "00".repeat(12) + mc.address.slice(2) + "00".repeat(32) - ), - "latest", - ], - jsonrpc: "2.0", - id: "test", - }; - mc.contract.currentProvider.send(getStoragePayload, (err, res) => { - if (err) reject(err); - else resolve(res.result); - }); - }); - console.log(`The balance storage slot contains ${storageSlot}.`); - - const balance = await mc.getBalance(mc.address); - console.log(`The contract now has balance: ${balance.toNumber()}.`); -} - -module.exports = async function (callback) { - try { - await exerciseContract(); - } catch (e) { - console.error(e); - } - callback(); -}; -``` - -Save it to `scripts/exercise.contract.js`. -We'll use it in just a bit. - -Next, you can run the following and see the contract being deployed. - -```sh -PRIVATE_KEY="0x..." truffle migrate --network emerald_testnet -``` - -Everything should be succeeding so far. - -Finally, run this line and observe some output. - -``` -> PRIVATE_KEY="0x..." truffle exec --network emerald_testnet scripts/exercise.contract.js` - -Sent some coins in 0xf415ab586ef1c6c61b84b3bd803ae322f375d1d3164aa8ac13c9ae83c698a002 -A Transfer(0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 42) was emitted. -The balance storage slot contains 0x2a. -The contract now has balance: 42 -``` - -Great! -That'll be the baseline for our confidential deployment. - -### Deploy to Sapphire (confidential EVM) - -#### Get some Sapphire Testnet tokens - -Now for the fun part. -As for Emerald, we need to configure the Sapphire network and get some tokens. -Hit up the one and only [Oasis Testnet faucet] and this time select "Sapphire". -Submit the form and on your way. - -#### Add the Sapphire Testnet to Truffle - -And another diff for your applying pleasure: - -```diff -diff --git a/truffle-config.js b/truffle-config.js -index 7af2f42..0cd9d36 100644 ---- a/truffle-config.js -+++ b/truffle-config.js -@@ -58,6 +58,11 @@ module.exports = { - new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.emerald.oasis.dev"), - network_id: 0xa515, - }, -+ // This is Testnet! If you want Mainnet, add a new network config item. -+ sapphire_testnet: { -+ provider: () => -+ new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev"), -+ network_id: 0x5aff, -+ }, - }, - - // Set default mocha options here, use special reporters etc. -``` - -#### Port to Sapphire - -Here's where things start to get interesting. -We're going to add confidentiality to this starter project in exactly two lines -of code. - -You'll need to grab the Sapphire compatibility library -([`@oasisprotocol/sapphire-paratime`]), so make that happen by issuing - -```sh -pnpm add -D @oasisprotocol/sapphire-paratime # npm also works -``` - -So far so good. -Next, import it by adding this line to the top of `truffle-config.js`: - -```typescript -const sapphire = require('@oasisprotocol/sapphire-paratime'); -``` - -That's the first line of code. -Here's the second: - -```diff -diff --git a/truffle-config.js b/truffle-config.js -index 0cd9d36..7db7cf8 100644 ---- a/truffle-config.js -+++ b/truffle-config.js -@@ -60,7 +60,7 @@ module.exports = { - }, - sapphire_testnet: { - provider: () => -- new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev"), -+ sapphire.wrap(new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev")), - network_id: 0x5aff, - }, - }, -``` - -This `wrap` function takes any kind of provider or signer you've got and turn -it into one that works with Sapphire and confidentiality. -For the most part, wrapping your signer/provider is the most you'll need to do -to get your dApp running on Sapphire, but that's not a complete story since an -unmodified contract may leak state through normal operation. - -And now for the moment we've all been waiting for: - -``` -> PRIVATE_KEY="0x..." truffle migrate --network sapphire_testnet -> PRIVATE_KEY="0x..." truffle exec --network sapphire_testnet scripts/exercise.contract.js - -Sent some coins in 0x6dc6774addf4c5c68a9b2c6b5e5634263e734d321f84012ab1b4cbe237fbe7c2. -A Transfer(0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 42) was emitted. -The balance storage slot contains 0x0. -The contract now has balance: 42. -``` - -So basically nothing changed, which is pretty much what we're going for. -But take a look at that second to last line where it says what's in the storage -slot. Before, it said `0x2a`, but now it says `0x0`. - -Clearly the slot does contain data or else the contract balance couldn't have -been returned. -What's happened here is that the Web3 gateway does not have the key used to -decrypt the storage slot, so a default value is returned. - -Indeed, the gateway does not even have the key needed to decrypt the _key_ in -the MKVS; it can tell _that_ a storage slot was written, but not which one -(although it can make a very good guess by reading the contract code). - -All in all, you can see that confidentiality is in effect, but it's not -something end-users need to think too much about. +[announcement]: https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat +[migration]: https://trufflesuite.com/docs/truffle/how-to/migrate-to-hardhat/ +[tutorial]: https://github.com/oasisprotocol/docs/blob/2f4a1a3c217b82687ab9440bf051762ae369ed45/docs/dapp/sapphire/quickstart.mdx +[example]: https://github.com/oasisprotocol/sapphire-paratime/tree/3a85e42e6c1cc090c28a521cf7df6353aa8a30c8/examples/truffle -[`@oasisprotocol/sapphire-paratime`]: https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime ## Create a Sapphire-Native dApp -Porting an existing Eth app is cool, and can already provide benefits like -protecting against MEV. +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]. @@ -242,7 +45,8 @@ Let's make it happen! ### Init a new Hardhat project -We're going to use Hardhat this time because it's very convenient to use. +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! 1. Make & enter a new directory 2. `npx hardhat@~2.12.0` then create a TypeScript project. @@ -258,7 +62,6 @@ We're going to use Hardhat this time because it's very convenient to use. ### Add the Sapphire Testnet to Hardhat Open up your `hardhat.config.ts` and drop in these lines. -They should remind you a lot about what happened with Truffle. ```diff diff --git a/hardhat.config.ts b/hardhat.config.ts @@ -376,9 +179,8 @@ Best of luck on your future forays into confidentiality! :::info Example -Visit the Sapphire ParaTime repository to download the final [Truffle] -[truffle-example] and [Hardhat][hardhat-example] examples of this -quickstart. +Visit the Sapphire ParaTime repository to download the [Hardhat][hardhat-example] +example of this quickstart. ::: @@ -390,6 +192,5 @@ quickstart. [social-media]: ../../get-involved/README.md#social-media-channels [guide]: guide.mdx -[truffle-example]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/truffle [hardhat-example]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/hardhat [`@oasisprotocol/sapphire-hardhat`]: https://www.npmjs.com/package/@oasisprotocol/sapphire-hardhat