diff --git a/docs/dapp/emerald/writing-dapps-on-emerald.mdx b/docs/dapp/emerald/writing-dapps-on-emerald.mdx index a67b5d6f5c..2cf8f57ea8 100644 --- a/docs/dapp/emerald/writing-dapps-on-emerald.mdx +++ b/docs/dapp/emerald/writing-dapps-on-emerald.mdx @@ -6,8 +6,8 @@ import {findSidebarItem} from '@site/src/sidebarUtils'; This tutorial will show you how to set up dApp development environment for Emerald to be able to write and deploy dApps on Oasis Emerald. -We will walk you through the Hardhat and Truffle configuration and - -for those who prefer a simpler web-only interface - the Remix IDE. +We will walk you through the Hardhat configuration and - for those who prefer +a simpler web-only interface - the Remix IDE. Oasis Emerald exposes an EVM-compatible interface so writing dApps isn't much different compared to the original Ethereum Network! @@ -327,248 +327,6 @@ Greeter deployed to: 0x6e8e9e0DBCa4EF4a65eBCBe4032e7C2a6fb7C623 [Node.js]: https://nodejs.org [ethers.js]: https://docs.ethers.io/v5/ -## Create dApp on Emerald with Truffle - -Truffle and its accompanying [web3.js] library is another popular smart -contract deployment tool. Let's follow [the official Truffle's quickstart -guide][truffle-quickstart] and unbox the MetaCoin example: - -``` -$ mkdir MetaCoin -$ cd MetaCoin -$ npx truffle unbox metacoin - -Starting unbox... -================= - -✔ Preparing to download box -✔ Downloading -✔ Cleaning up temporary files -✔ Setting up box - -Unbox successful, sweet! - -Commands: - - Compile contracts: truffle compile - Migrate contracts: truffle migrate - Test contracts: truffle test -``` - -To compile and test the contract type: - -``` -$ npx truffle test -Using network 'test'. - - -Compiling your contracts... -=========================== -> Compiling ./test/TestMetaCoin.sol -> Artifacts written to /tmp/test--1052348-l4q3zOSy9nRA -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang - - - - TestMetaCoin - ✓ testInitialBalanceUsingDeployedContract (112ms) - ✓ testInitialBalanceWithNewMetaCoin (106ms) - - Contract: MetaCoin - ✓ should put 10000 MetaCoin in the first account (59ms) - ✓ should call a function that depends on a linked library (78ms) - ✓ should send coin correctly (185ms) - - - 5 passing (6s) -``` - -This spawns an instance of Truffle Develop blockchain in the background with a -number of prepopulated ETH accounts and runs the tests. - -Now, let's add support to Truffle for reading the private key stored in the -environment variable. Add the `@truffle/hdwallet-provider` package: - -``` -$ npm i @truffle/hdwallet-provider --save-dev -``` - -Import the library by adding the following line at the beginning of your -`truffle-config.js`: - -`const HDWalletProvider = require("@truffle/hdwallet-provider");` - -Open `truffle-config.js` and configure the `emerald_local`, `emerald_testnet` -and `emerald_mainnet` networks: - -``` -emerald_local: { - url: "http://localhost:8545", - provider: function() { - return new HDWalletProvider(process.env.PRIVATE_KEYS.split(","), "http://localhost:8545"); - }, - network_id: "*" -}, -emerald_testnet: { - url: "https://testnet.emerald.oasis.dev:8545", - provider: function() { - return new HDWalletProvider(process.env.PRIVATE_KEY, "https://testnet.emerald.oasis.dev"); - }, - network_id: "*" -}, -emerald_mainnet: { - url: "https://emerald.oasis.dev:8545", - provider: function() { - return new HDWalletProvider(process.env.PRIVATE_KEY, "https://emerald.oasis.dev"); - }, - network_id: "*" -} -``` - -The MetaCoin example is somewhat specific in that it expects at least two -private keys for running the token transfer test. That's why we use the -`.split(",")` in the `emerald_local` network configuration above and we assign -two private keys to the environment variable. If you are running [emerald-dev], -copy and paste any two of the generated private keys. - -``` -export PRIVATE_KEYS="0xYOUR_FIRST_EMERALD_PRIVATE_KEY,0xYOUR_SECOND_EMERALD_PRIVATE_KEY" -``` - -When we run the tests Truffle will deploy the contract with its dependencies -and call the contract numerous times so it may take a few moments to complete. - -``` -$ truffle test --network emerald_local -Using network 'emerald_local'. - - -Compiling your contracts... -=========================== -> Compiling ./test/TestMetaCoin.sol -> Artifacts written to /tmp/test--1083354-x87wt3FdmfDE -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang - - - - TestMetaCoin - ✓ testInitialBalanceUsingDeployedContract (1091ms) - ✓ testInitialBalanceWithNewMetaCoin (913ms) - - Contract: MetaCoin - ✓ should put 10000 MetaCoin in the first account (349ms) - ✓ should call a function that depends on a linked library (677ms) -account one: 0x90adE3B7065fa715c7a150313877dF1d33e777D5 -account two: 0x33a8Ba274FEdFeed6A08d09eC524a1E1A6Da8262 - ✓ should send coin correctly (2795ms) - - - 5 passing (26s) -``` - -In order to deploy the contracts to the Testnet and finally the Mainnet run the -`migrate` Truffle command and use the `emerald_testnet` or `emerald_mainnet` -network accordingly. For the Mainnet, you would run something like this and in -a few rounds - depending on the network congestion - the contracts will be -deployed: - -``` -$ PRIVATE_KEY=0xYOUR_MAINNET_PRIVATE_KEY truffle migrate --network emerald_mainnet - -Compiling your contracts... -=========================== -> Everything is up to date, there is nothing to compile. - - - -Starting migrations... -====================== -> Network name: 'emerald_mainnet' -> Network id: 42262 -> Block gas limit: 21000000 (0x1406f40) - - -1_initial_migration.js -====================== - - Deploying 'Migrations' - ---------------------- - > transaction hash: 0x1630945ac8abfe6395a2e2627bd0acfffcf4bda9e107943cb3e4d6ef1d0905d4 - > Blocks: 1 Seconds: 44 - > contract address: 0xFaeA7eda8Be7AC83f811019094D0065D28F52c7c - > block number: 93914 - > block timestamp: 1642176860 - > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5 - > balance: 0 - > gas used: 209087 (0x330bf) - > gas price: 0 gwei - > value sent: 0 ETH - > total cost: 0 ETH - - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0 ETH - - -2_deploy_contracts.js -===================== - - Deploying 'ConvertLib' - ---------------------- - > transaction hash: 0xf2c53938773c316051f4ce98395e5df21cfcf0c686f634c1079725e04b9c556c - > Blocks: 2 Seconds: 80 - > contract address: 0xA0FB05d6Ce497beb162C4EbA4F203544B18A3f31 - > block number: 93918 - > block timestamp: 1642177009 - > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5 - > balance: 0 - > gas used: 121235 (0x1d993) - > gas price: 0 gwei - > value sent: 0 ETH - > total cost: 0 ETH - - - Linking - ------- - * Contract: MetaCoin <--> Library: ConvertLib (at address: 0xA0FB05d6Ce497beb162C4EbA4F203544B18A3f31) - - Deploying 'MetaCoin' - -------------------- - > transaction hash: 0x2c5e8177df03d643e56a37b64cbe660420b114ffec097dc5d793bfc666af8e16 - > Blocks: 2 Seconds: 60 - > contract address: 0x5a1C04012bc233c898aebb8BB4353F80D96f3dD2 - > block number: 93920 - > block timestamp: 1642177073 - > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5 - > balance: 0 - > gas used: 361168 (0x582d0) - > gas price: 0 gwei - > value sent: 0 ETH - > total cost: 0 ETH - - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0 ETH - - -Summary -======= -> Total deployments: 3 -> Final cost: 0 ETH -``` - -In the output above, the MetaCoin contract has been successfully deployed to -`0x5a1C04012bc233c898aebb8BB4353F80D96f3dD2` address on the Mainnet. - -[web3.js]: https://web3js.readthedocs.io/en/v1.5.2/ -[truffle-quickstart]: https://trufflesuite.com/docs/truffle/quickstart.html - ## Create dApp on Emerald with Remix - Ethereum IDE [Remix] is a popular web IDE for swift development, deployment and testing @@ -620,6 +378,20 @@ share them with us on the [#emerald-paratime Discord channel][discord]. ## Troubleshooting +### Truffle Support + +:::info Sunsetting Truffle + +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]. + +::: + +[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/207a7b1a42b4afdac70b925e755f5546723e4831/docs/dapp/emerald/writing-dapps-on-emerald.mdx#L330-L570 + ### Deployment of my contract timed out on Testnet or Mainnet Emerald validators, similar to Ethereum ones, order the execution of @@ -632,8 +404,8 @@ required gas price on Emerald. This value should already be propagated automatically by the web3 endpoint, but your deployment configuration might have ignored it. -Finally, consider increasing the `gasPrice` parameter in Hardhat/Truffle config -files by a fraction (e.g. 10% or 20%). This will require more ROSE from your +Finally, consider increasing the `gasPrice` parameter in the Hardhat config +file by a fraction (e.g. 10% or 20%). This will require more ROSE from your wallet to deploy the contract, but you will also increase the chance of your transaction being included in the block. diff --git a/docs/dapp/sapphire/guide.mdx b/docs/dapp/sapphire/guide.mdx index 8486c6026d..e1bc50e82b 100644 --- a/docs/dapp/sapphire/guide.mdx +++ b/docs/dapp/sapphire/guide.mdx @@ -121,7 +121,7 @@ it'll work just fine. ### Languages & Frameworks Sapphire is programmable using any language that targets the EVM, such as Solidity -and Vyper. If you prefer to use an Ethereum framework like Hardhat or Truffle, you +or Vyper. If you prefer to use an Ethereum framework like Hardhat or Foundry, you can also use those with Sapphire; all you need to do is set your Web3 gateway URL. You can find the details of the Oasis Sapphire Web3 gateway [here](/dapp/sapphire#web3-gateway). diff --git a/docs/dapp/sapphire/quickstart.mdx b/docs/dapp/sapphire/quickstart.mdx index 73621a7a61..e303fa3abd 100644 --- a/docs/dapp/sapphire/quickstart.mdx +++ b/docs/dapp/sapphire/quickstart.mdx @@ -4,275 +4,34 @@ import {findSidebarItem} from '@site/src/sidebarUtils'; # Quickstart

- +

-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 -### Setup - -Start by installing [Truffle](https://github.com/trufflesuite/truffle#install). - -Then, run these commands in your terminal: - -```sh -mkdir MetaCoin && cd MetaCoin -truffle unbox MetaCoin -git init -git add :/ && git commit -m "Initial commit" -pnpm init && pnpm add -D @truffle/hdwallet-provider -``` - -:::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/ - -#### Add the Emerald Testnet to Truffle - -Apply this patch to `truffle-config.js`: - -```diff -diff --git a/truffle-config.js b/truffle-config.js -index 68d534c..15c671d 100644 ---- a/truffle-config.js -+++ b/truffle-config.js -@@ -22,7 +22,7 @@ - // const mnemonic = process.env["MNEMONIC"]; - // const infuraProjectId = process.env["INFURA_PROJECT_ID"]; - --// const HDWalletProvider = require('@truffle/hdwallet-provider'); -+const HDWalletProvider = require('@truffle/hdwallet-provider'); - - module.exports = { - /** -@@ -53,6 +53,14 @@ module.exports = { - // network_id: 5, // Goerli's id - // chain_id: 5 - // } -+ // This is Testnet! If you want Mainnet, add a new network config item. -+ emerald_testnet: { -+ provider: () => -+ new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.emerald.oasis.dev"), -+ network_id: 0xa515, -+ }, - }, - - // Set default mocha options here, use special reporters etc. -``` - -#### 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. +[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 -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. - -[`@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]. @@ -286,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. @@ -302,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 @@ -332,9 +91,17 @@ index 414e974..49c95f9 100644 ``` By importing `@oasisprotocol/sapphire-hardhat` at the top of the config file, -any network config entry corresponding to the Sapphire's chain ID will +**any network config entry corresponding to the Sapphire's chain ID will automatically be wrapped with Sapphire specifics for encrypting and signing the -transactions. +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. + +[Oasis Testnet faucet]: https://faucet.testnet.oasis.dev ### Get the Contract @@ -414,9 +181,17 @@ 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. + +::: + +:::info Example + +If your project involves building a web frontend, we recommend that you check +out the official [Oasis starter] files. + +[Oasis starter]: https://github.com/oasisprotocol/demo-starter ::: @@ -428,6 +203,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