diff --git a/README.md b/README.md index 0d42d411..536b8708 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ This repository includes all relevant Sapphire and dependencies organized into the following directories: - [`clients`](./clients): the Go, Python and JavaScript/TypeScript clients -- [`contracts`](./contracts): Sapphire and [OPL](https://docs.oasis.io/dapp/opl/) smart contracts +- [`contracts`](./contracts): Sapphire and [OPL](https://docs.oasis.io/build/opl/) smart contracts - [`docs`](./docs): topic-oriented Sapphire documentation - [`examples`](./examples/): sample code snippets in popular Ethereum development environments @@ -76,7 +76,7 @@ development environments ## Documentation The Sapphire documentation is deployed as part of the official -[Oasis documentation](https://docs.oasis.io/dapp/sapphire/). To make changes +[Oasis documentation](https://docs.oasis.io/build/sapphire/). To make changes visible on the docs website: 1. Merge any changes in the `docs` folder to the `main` branch. diff --git a/clients/go/README.md b/clients/go/README.md index b7db4857..e8d36a16 100644 --- a/clients/go/README.md +++ b/clients/go/README.md @@ -6,7 +6,7 @@ style. [@oasisprotocol/sapphire-paratime]: https://pkg.go.dev/github.com/oasisprotocol/sapphire-paratime/go/ -[Sapphire ParaTime]: https://docs.oasis.io/dapp/sapphire +[Sapphire ParaTime]: https://docs.oasis.io/build/sapphire ## Building @@ -96,5 +96,5 @@ _ = c.SendTransaction(ctx, signedTx) ## See Also - [Oasis Testnet Faucet](https://faucet.testnet.oasis.io/) -- [Creating dapps for Sapphire](https://docs.oasis.io/dapp/sapphire/quickstart) +- [Creating dapps for Sapphire](https://docs.oasis.io/build/sapphire/quickstart) - [How to Transfer ROSE into an EVM ParaTime](https://docs.oasis.io/general/manage-tokens/how-to-transfer-rose-into-paratime/) diff --git a/clients/js/README.md b/clients/js/README.md index dd04d4fd..3093dacd 100644 --- a/clients/js/README.md +++ b/clients/js/README.md @@ -11,7 +11,7 @@ The Sapphire wrapper with automatically encrypt the `eth_call`, `eth_estimateGas and `eth_signTransaction` JSON-RPC calls [@oasisprotocol/sapphire-paratime]: https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime -[sapphire paratime]: https://docs.oasis.io/dapp/sapphire/ +[sapphire paratime]: https://docs.oasis.io/build/sapphire/ _If your dapp doesn't port in under 10 minutes, it's a bug!_
If you have more than a little trouble, please file an issue.
@@ -59,5 +59,5 @@ signed queries manually using the `overrides` parameter to `SignedCallDataPack.m ## See Also - [Oasis Testnet Faucet](https://faucet.testnet.oasis.io/) -- [Creating dapps for Sapphire](https://docs.oasis.io/dapp/sapphire/quickstart) +- [Creating dapps for Sapphire](https://docs.oasis.io/build/sapphire/quickstart) - [How to Transfer ROSE into an EVM ParaTime](https://docs.oasis.io/general/manage-tokens/how-to-transfer-rose-into-paratime/) diff --git a/contracts/README.md b/contracts/README.md index 1a55d8c8..364cccd4 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -34,8 +34,8 @@ contract RandomNumber { ## Documentation -See the user's guide for [Sapphire](https://docs.oasis.io/dapp/sapphire/) and -[OPL](https://docs.oasis.io/dapp/opl/). +See the user's guide for [Sapphire](https://docs.oasis.io/build/sapphire/) and +[OPL](https://docs.oasis.io/build/opl/). The generated API reference is hosted at [api.docs.oasis.io](https://api.docs.oasis.io/sol/sapphire-contracts). diff --git a/docs/README.mdx b/docs/README.mdx index 62247cf9..6a252286 100644 --- a/docs/README.mdx +++ b/docs/README.mdx @@ -19,6 +19,7 @@ crypto gaming ### Getting Started Develop and deploy a dApp on Sapphire: + - follow along with a video walkthrough via [quickstart][quickstart] - start with a working dApp [demo][demo] - explore showcase dApps deployed on Sapphire on the [playground][playground] @@ -29,16 +30,18 @@ Develop and deploy a dApp on Sapphire: ### Understanding EVM compatibility -Get to know the differences between Sapphire and Ethereum, and learn about -the high level concepts of developing a confidential smart contract with our -[guide][guide]. +Get to know the differences between [Sapphire and Ethereum], and learn about +the high level [concepts] of developing DApps. -[guide]: ./guide.mdx +[Sapphire and Ethereum]: ./ethereum.md +[concepts]: ./build/concept.mdx ### Building on Sapphire Take your existing dApp building knowledge and add Sapphire with our developer -[cheatsheet](./images/cheatsheet.pdf). +[cheatsheet](./images/cheatsheet.pdf) or visit the [build] chapter. + +[build]: ./build/README.mdx ### Network Information @@ -59,5 +62,5 @@ Visit the [faucet][faucet] to obtain testnet tokens for development purposes. findSidebarItem('/node/run-your-node/paratime-node'), findSidebarItem('/node/run-your-node/paratime-client-node'), findSidebarItem('/node/web3'), - findSidebarItem('/dapp/tools/other-paratimes/'), + findSidebarItem('/build/tools/other-paratimes/'), ]} /> diff --git a/docs/build/README.mdx b/docs/build/README.mdx new file mode 100644 index 00000000..dc39d87e --- /dev/null +++ b/docs/build/README.mdx @@ -0,0 +1,76 @@ +--- +description: Build DApps on Sapphire +--- + +# Build + +As Sapphire is EVM-compatible, you can use the same dev tooling as you would +when building on Ethereum. Additionally, we build tools to support you in +creating secure and confidential DApps. + +Feel free to check out the [concept] page to get a better understanding of the +transaction flow and the contract state. + +[concept]: ./concept.mdx + +## Contract Development + +Sapphire is programmable using any language that targets the EVM, such as Solidity, +Fe 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 endpoints +[here](../network.mdx#rpc-endpoints). + + +### Development Environments + +- [Build with Hardhat] +- [Build with Foundry] + +[Build with Hardhat]: ./hardhat.md +[Build with Foundry]: ./foundry.md + +### Features + +- [Deployment and Proxies][deployment] +- [Gasless and Onchain Signing][gasless] +- [Security considerations][security] +- [View-call authentication][view-call] +- [Randomness, Subcalls and More Precompiles][sapphire-contracts] + +[deployment]: ./deployment.md +[gasless]: ./gasless.md +[security]: ./security.md +[view-call]: ./authentication.md +[sapphire-contracts]: https://api.docs.oasis.io/sol/sapphire-contracts + +## Frontend Development + +We support the common frontend libraries: + +- [Ethers v6][ethers] +- [Viem][viem] +- [Wagmi][wagmi] + +[ethers]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/ethers-v6 +[viem]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/viem-v2 +[wagmi]:https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/wagmi-2 + +## Backend Development + +If you want to connect and execute transactions from your backend, visit our +[clients] chapter to see what other languages we support + +[clients]: clients.md + +## Examples + +See our [examples] page for demo DApps that bring all the above together. + +[examples]: ../examples.mdx + +Should you have any questions or ideas to share, feel free to reach out to us +on [discord and other social media channels][social-media]. + +[social-media]: https://github.com/oasisprotocol/docs/blob/main/docs/get-involved/README.md#social-media-channels + diff --git a/docs/authentication.md b/docs/build/authentication.md similarity index 99% rename from docs/authentication.md rename to docs/build/authentication.md index a4f61e01..518d31c3 100644 --- a/docs/authentication.md +++ b/docs/build/authentication.md @@ -74,7 +74,7 @@ which created the contract, calling `isOwner` will return: * `false`, with `sapphire.wrap` but without an attached signer * `true`, with `sapphire.wrap` and an attached signer * `true`, if called via the contract which created it -* `true`, if called via transaction + * `true`, if called via transaction ## Caching Signed Queries diff --git a/docs/browser.md b/docs/build/browser.md similarity index 92% rename from docs/browser.md rename to docs/build/browser.md index a0ec76e1..18b3a018 100644 --- a/docs/browser.md +++ b/docs/build/browser.md @@ -44,12 +44,11 @@ access them!** The contract in the Hardhat boilerplate is ERC-20-compatible and emits the `transfer` event. If your wish to preserve confidentiality, you can comment -out [line 66]. Read [the guide](guide.mdx#contract-logs) to learn more. +out [line 66]. Read the [concept] chapter to learn more. ::: -[`wagmi`]: https://wagmi.sh/ -[`viem`]: https://viem.sh/ +[concept]: ./concept.mdx#contract-logs ## Signing Sapphire Calls and Transactions in Browser @@ -155,7 +154,7 @@ npm run start If all goes well the web server will spin up and your browser should automatically open `http://localhost:3000`. -![Hardhat boilerplate frontend](images/hardhat-boilerplate-frontend1.png) +![Hardhat boilerplate frontend](../images/hardhat-boilerplate-frontend1.png) Go ahead and connect the wallet. If you haven't done it yet, you will have to add the [Sapphire ParaTime Testnet network to your @@ -163,13 +162,13 @@ Metamask][sapphire-testnet]. Once connected, the frontend will make an unsigned call to the `balanceOf` view and show you the amount of `MHT`s in your selected Metamask account. -![MHT balance of your account](images/hardhat-boilerplate-frontend2.png) +![MHT balance of your account](../images/hardhat-boilerplate-frontend2.png) Next, let's transfer some `MHT`s. Fill in the amount, the address and hit the *Transfer* button. Metamask will show you the popup to sign and submit the transfer transaction. Once confirmed, Metamask will both **sign and encrypt** the transaction. -![Sign and encrypt the transfer transaction](images/hardhat-boilerplate-frontend3.png) +![Sign and encrypt the transfer transaction](../images/hardhat-boilerplate-frontend3.png) Once the transaction is processed, you will get a notification from Metamask and the balance in the dApp will be updated. @@ -207,14 +206,13 @@ we recommend that you check out the official [Oasis starter] files. ::: [block explorer]: https://explorer.oasis.io/testnet/sapphire/tx/0x3303dea5d48291d1564cad573f21fc71fcbdc2b862e17e056287fd9207e3bc53 -[guide-transaction-calls]: guide.mdx#transactions--calls +[guide-transaction-calls]: ./concept.mdx#transactions--calls [Hardhat boilerplate repo]: https://github.com/NomicFoundation/hardhat-boilerplate [Hardhat boilerplate]: https://hardhat.org/tutorial/boilerplate-project -[Hardhat tutorial]: https://hardhat.org/tutorial [line 66]: https://github.com/NomicFoundation/hardhat-boilerplate/blob/13bd712c1285b2de572f14d20e6a750ae08565c0/contracts/Token.sol#L66 -[quickstart]: quickstart.mdx#add-the-sapphire-testnet-to-hardhat -[sapphire-testnet]: ./network.mdx#rpc-endpoints +[quickstart]: ../quickstart.mdx#add-the-sapphire-testnet-to-hardhat +[sapphire-testnet]: ../network.mdx#rpc-endpoints [Sapphire ParaTime examples]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/hardhat-boilerplate [social-media]: https://github.com/oasisprotocol/docs/blob/main/docs/get-involved/README.md#social-media-channels [pnpm]: https://pnpm.io -[TEST tokens]: quickstart.mdx#get-some-sapphire-testnet-tokens +[TEST tokens]: ../quickstart.mdx#get-some-sapphire-testnet-tokens diff --git a/docs/build/clients.md b/docs/build/clients.md new file mode 100644 index 00000000..e9b0335d --- /dev/null +++ b/docs/build/clients.md @@ -0,0 +1,15 @@ +--- +description: Different clients of Sapphire +--- + +# Clients + +Sapphire has three clients in different programming languages: + +- Sapphire [JS] +- Sapphire [Go] +- Sapphire [Py] + +[JS]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/js/README.md +[Go]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/go/README.md +[Py]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/py/README.md diff --git a/docs/build/concept.mdx b/docs/build/concept.mdx new file mode 100644 index 00000000..b0567865 --- /dev/null +++ b/docs/build/concept.mdx @@ -0,0 +1,100 @@ +--- +description: Sapphire concepts +--- + +import DocCard from '@theme/DocCard'; +import {findSidebarItem} from '@site/src/sidebarUtils'; + +# Concept + +### Transactions & Calls + +{/*-- https://github.com/oasisprotocol/docs/blob/455980674563cad92ff1e1b62a7a5f2d4d6809f0/docs/general/images/architecture/client-km-compute.svg -->*/} +![Client, Key Manager, Compute Node diagram](../../../general/images/architecture/client-km-compute.svg) + +The figure above illustrates the flow of a **confidential smart contract +transaction** on Sapphire. + +Transactions and calls must be encrypted and signed for maximum security. +The [@oasisprotocol/sapphire-paratime] npm package will make your life +easy. It'll handle cryptography and signing for you. + +You should be aware that taking actions based on the value of private data may +**leak the private data through side channels** like time spent, gas use and +accessed memory locations. If you need to branch on private data, you should in +most cases ensure that both branches exhibit the same time/gas and storage +patterns. + +You can also make **confidential smart contract calls** on Sapphire. If you +use `msg.sender` for access control in your contract, the call **must be +signed**, otherwise `msg.sender` will be zeroed. On the other hand, set the +`from` address to all zeros, if you want to avoid annoying signature popups in +the user's wallet for calls that do not need to be signed. The JS library will +do this for you. + +:::note + +Inside the smart contract code, there is no way of knowing whether the +client's call data were originally encrypted or not. + +::: + +
+ Detailed confidential smart contract transaction flow on Sapphire + +![Diagram of the detailed confidential smart contract transaction flow on Sapphire](../diagrams/c10l-smart-contract-tx.mmd.svg) + +
+ +
+ Detailed confidential smart contract call flow on Sapphire + +![Diagram of the detailed confidential smart contract call flow on Sapphire](../diagrams/c10l-smart-contract-call.mmd.svg) + +
+ +### Contract State + +The Sapphire state model is like Ethereum's except for all state being encrypted +and not accessible to anyone except the contract. The contract, executing in an +active (attested) Oasis compute node is the only entity that can request its +state encryption key from the Oasis key manager. Both the keys and values of the +items stored in state are encrypted, but the **size of either is not hidden**. Your +app may need to pad state items to a constant length, or use other obfuscation. +Observers may also be able to infer computation based on storage access patterns, +so you may need to obfuscate that, too. See [Security chapter] for more +recommendations. + +[Security chapter]: ./security.md#storage-access-patterns + +:::danger Contract state leaks a fine-grained access pattern + +Contract state is backed by an encrypted key-value store. However, the trace of +encrypted records is leaked to the compute node. As a concrete example, an ERC-20 +token transfer would leak which encrypted record is for the sender's account +balance and which is for the receiver's account balance. Such a token would be +traceable from sender address to receiver address. Obfuscating the storage access +patterns may be done by using an ORAM implementation. + +::: + +Contract state may be made available to third parties through logs/events, or +explicit getters. + +### Contract Logs + +Contract logs/events (e.g., those emitted by the Solidity `emit` keyword) +are exactly like Ethereum. Data contained in events is *not* encrypted. +Precompiled contracts are available to help you encrypt data that you can +then pack into an event, however. + +:::danger Unmodified contracts may leak state through logs + +Base contracts like those provided by OpenZeppelin often emit logs containing +private information. If you don't know they're doing that, you might undermine +the confidentiality of your state. As a concrete example, the ERC-20 spec +requires implementers to emit an `event Transfer(from, to, amount)`, which is +obviously problematic if you're writing a confidential token. What you can +do instead is fork that contract and remove the offending emissions. + +::: diff --git a/docs/deployment.md b/docs/build/deployment.md similarity index 100% rename from docs/deployment.md rename to docs/build/deployment.md diff --git a/docs/build/foundry.md b/docs/build/foundry.md new file mode 100644 index 00000000..bb14e68b --- /dev/null +++ b/docs/build/foundry.md @@ -0,0 +1,21 @@ +--- +description: Use Sapphire with Foundry +--- + +# Foundry + +:::caution Under Construction + +This page is **under construction**. Content may be incomplete or subject to +change. + +::: + +Foundry is a fast, portable, and modular framework designed to streamline +Solidity development and testing by providing a robust set of tools for +compiling, deploying, and verifying smart contracts. + +If you’re hearing about Foundry for the first time, make sure to check out the +official [Foundry documentation]. + +[Foundry documentation]: https://book.getfoundry.sh/ diff --git a/docs/gasless.md b/docs/build/gasless.md similarity index 98% rename from docs/gasless.md rename to docs/build/gasless.md index 0a1cbf91..09e7a9d9 100644 --- a/docs/gasless.md +++ b/docs/build/gasless.md @@ -40,7 +40,7 @@ checks whether the transaction is valid, wraps it into a meta-transaction in [EIP-155] format. These steps are executed as a confidential call. Finally, the user submits the generated transaction to the network. -![Diagram of the On-Chain Signing](images/gasless-on-chain-signer.svg) +![Diagram of the On-Chain Signing](../images/gasless-on-chain-signer.svg) ### EIP155Signer @@ -258,7 +258,6 @@ creators can close the poll. [demo-voting]: https://github.com/oasisprotocol/demo-voting [demo-voting-playground]: https://playground.oasis.io/demo-voting -[dao-opl]: https://github.com/oasisprotocol/docs/blob/main/docs/dapp/opl/host.md [EIP-155]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md ## Gas Station Network @@ -267,7 +266,7 @@ creators can close the poll. Sapphire in a forked `@oasislabs/opengsn-cli` package. The diagram below illustrates a flow for signing a transaction by using a GSN[^1]. -![Diagram of the Gas Station Network Flow](images/gasless-gsn-flow.jpg) +![Diagram of the Gas Station Network Flow](../images/gasless-gsn-flow.jpg) [^1]: The GSN flow diagram is courtesy of [OpenGSN documentation][opengsn-docs]. @@ -361,6 +360,7 @@ requests and forward them to the relay hub on Sapphire Testnet. We can test whether a relayed request can be forwarded and processed correctly. Scroll up to find the GSN deployment response and use the following parameters: + - `Forwarder` as `--to`, - `Paymaster` as `--paymaster`, - your account address as `--from` diff --git a/docs/build/hardhat.md b/docs/build/hardhat.md new file mode 100644 index 00000000..02d295d1 --- /dev/null +++ b/docs/build/hardhat.md @@ -0,0 +1,109 @@ +--- +description: Use Sapphire with hardhat +--- + +# Hardhat + +Hardhat is a versatile development environment for Ethereum, designed to +streamline tasks like compiling, testing, and deploying smart contracts. It +offers a modular toolkit and an intuitive workflow that helps developers focus +on building robust decentralized applications. + +If you’re reading about Hardhat for the first time, be sure to explore the +official [Hardhat documentation] for more in-depth information. + +[Hardhat documentation]: https://hardhat.org/docs + +## Quickstart + +Our [Quickstart] chapter is the best way to start building on Oasis Sapphire. +It guides you through setting up your environment and deploying your first +contract using Hardhat. You'll quickly learn the basics of Hardhat while +exploring Sapphire's privacy-preserving features. + +Check out the [Quickstart] to begin your journey! + +## Local Development and Testing + +For local development and testing, Oasis provides a Docker container that +simulates the Sapphire blockchain. This setup works similarly to the Hardhat +Node, allowing you to interact with a local instance of the Sapphire ParaTime +for fast, iterative development. + +To learn how to set up and use the local Sapphire environment, check out the +[Localnet] chapter under the Tools section of the documentation. It provides +detailed instructions on configuring and running the local blockchain, making +it easy to test and debug your contracts before deploying them to a live +network. + +### Localnet Hardhat config + +To use the Localnet with Hardhat, add the network as follows: + +```js title="hardhat.config.ts" + import { HardhatUserConfig } from "hardhat/config"; + import "@nomicfoundation/hardhat-toolbox"; + + //accounts script +const TEST_HDWALLET = { + mnemonic: "test test test test test test test test test test test junk", + path: "m/44'/60'/0'/0", + initialIndex: 0, + count: 20, + passphrase: "", +}; +const accounts = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : TEST_HDWALLET; + + const config: HardhatUserConfig = { + solidity: "0.8.19", + // highlight-start + networks: { + 'sapphire-localnet': { + url: "http://localhost:8545", // Localnet RPC URL + chainId: 23294, // Sapphire Localnet chain ID + accounts + }, + }, + // highlight-end + }; +``` + +You can now use the standard test accounts to run your Hardhat tests: + + ```shell +npx hardhat test --network sapphire-localnet +``` + +## Hardhat Provider + +The `@oasisprotocol/sapphire-hardhat` package provides a custom Hardhat +provider that enables encrypted transactions when working with Oasis Sapphire. +This makes it easy to test and run tasks involving confidential smart contracts +directly within your Hardhat setup. + +### Installation + +To add the provider to your project, run: + + ```shell npm2yarn + npm install -D @oasisprotocol/sapphire-hardhat + ``` + +Next, import it in your `hardhat.config.ts` above the rest of your plugins so +that the provider gets wrapped before anything else starts to use it. + +```js +// ESM +import '@oasisprotocol/sapphire-hardhat'; + +// CommonJS +require('@oasisprotocol/sapphire-hardhat'); + +/** All other plugins must go below this one! **/ +``` + +The Hardhat Ethers provider is now wrapped for Sapphire and will encrypt your +transactions on use. + +[Quickstart]: ../quickstart.mdx +[Localnet]: https://github.com/oasisprotocol/docs/blob/main/docs/build/tools/localnet.mdx diff --git a/docs/security.md b/docs/build/security.md similarity index 100% rename from docs/security.md rename to docs/build/security.md diff --git a/docs/ethereum.md b/docs/ethereum.md new file mode 100644 index 00000000..da872204 --- /dev/null +++ b/docs/ethereum.md @@ -0,0 +1,89 @@ +--- +description: Differences to Ethereum +--- + +# Sapphire vs Ethereum + +Sapphire is generally compatible with Ethereum, the EVM, and all the user and +developer tooling that you are used to. In addition to confidentiality +features, you get a few extra benefits including the ability to **generate +private entropy**, and **make signatures on-chain**. An example of a dApp that +uses both is an HSM contract that generates an Ethereum wallet and signs +transactions sent to it via transactions. + +There are also a few breaking changes compared to Ethereum though, but we think +that you'll quickly grasp them: + + - [Encrypted Contract State](#encrypted-contract-state) + - [End-to-End Encrypted Transactions and Calls](#end-to-end-encrypted-transactions-and-calls) + - [`from` Address is Zero for Unsigned Calls](#from-address-is-zero-for-unsigned-calls) + - [Override `receive` and `fallback` when Funding the Contract](#override-receive-and-fallback-when-funding-the-contract) + - [Instant Finality](#instant-finality) + +Read below to learn more about them. Otherwise, Sapphire is like Emerald, a +fast, cheap Ethereum. + +## Encrypted Contract State + +The contract state is only visible to the contract that wrote it. With respect +to the contract API, it's as if all state variables are declared as `private`, +but with the further restriction that not even full nodes can read the values. +Public or access-controlled values are provided instead through explicit +getters. + +Calling `eth_getStorageAt()` will return zero. + +## End-to-End Encrypted Transactions and Calls + +Transactions and calls are end-to-end encrypted into the contract. Only the +caller and the contract can see the data sent to/received from the ParaTime. +This ends up defeating some utility of block explorers, however. + +The status of the transaction is public and so are the error code, the revert +message and logs (emitted events). + +## `from` Address is Zero for Unsigned Calls + +The `from` address using of calls is derived from a signature attached to the +call. Unsigned calls have their sender set to the zero address. This allows +contract authors to write getters that release secrets to authenticated callers +(e.g. by checking the `msg.sender` value), but without requiring a transaction +to be posted on-chain. + +## Override `receive` and `fallback` when Funding the Contract + +In Ethereum, you can fund a contract by sending Ether along the transaction in +two ways: + +1. a transaction must call a *payable* function in the contract, or +2. not calling any specific function (i.e. empty *calldata*). In this case, + the payable `receive()` and/or `fallback()` functions need to be defined in + the contract. If no such functions exist, the transaction will revert. + +The behavior described above is the same in Sapphire when using EVM transactions +to fund a contract. + +However, the Oasis Network also uses [Oasis-native transactions] such as a +deposit to a ParaTime account or a transfer. In this case, **you will be able to +fund the contract's account even though the contract may not implement payable +`receive()` or `fallback()`!** Or, if these functions do exist, **they will not +be triggered**. You can send such Oasis-native transactions by using the [Oasis +CLI] for example. + +[Oasis-native transactions]: https://github.com/oasisprotocol/docs/blob/main/docs/general/manage-tokens/README.mdx +[Oasis CLI]: https://github.com/oasisprotocol/cli/blob/master/docs/README.md + +## Instant Finality + +The Oasis Network is a proof of stake network where 2/3+ of the validator nodes +need to verify each block in order to consider it final. However, in Ethereum +the signatures of those validator nodes can be submitted minutes after the block +is proposed, which makes the block proposal mechanism independent of the +validation, but adds uncertainty if and when will the proposed block actually be +finalized. + +In the Oasis Network, the 2/3+ of signatures need to be provided immediately +after the block is proposed and **the network will halt, until the required +number signatures are provided**. This means that you can rest assured that any +validated block is final. As a consequence, the cross-chain bridges are more +responsive yet safe on the Oasis Network. diff --git a/docs/examples.mdx b/docs/examples.mdx new file mode 100644 index 00000000..6d2e93ff --- /dev/null +++ b/docs/examples.mdx @@ -0,0 +1,54 @@ +--- +description: Examples build with Sapphire +--- + +# Examples + +## Randomness + +:::info [Example Oasis Swag Wheel][rng-example] + +[Example dapp][rng-example] which uses onchain RNG to determine which Swag a participant wins. + +::: + +## Confidential Voting + +:::info [Example VoTEE][votee-example] + +[Voting example][votee-example] to vote for the favorite Oasis mascot, see also [voTEE.oasis.io]. + +::: + +:::info [Example Blockvote][voting-example] + +[Example][voting-example] for general confidential and gasless voting, see also [vote.oasis.io]. + +::: + +## SIWE + +:::info [Example SIWE][siwe-example] + +Sign in with Ethereum (SIWE) [example dapp][siwe-example]. + +::: + +## Onchain signing + +:::info [Example Onchain signing][onchain-signer] + +Onchain transaction generation and signing [example][onchain-signer]. + +::: + +Find more examples on [playground.oasis.io]. + +[rng-example]: https://github.com/oasisprotocol/demo-oasisswag +[voting-example]: https://github.com/oasisprotocol/dapp-blockvote +[vote.oasis.io]: https://vote.oasis.io +[votee-example]: https://github.com/oasisprotocol/dapp-votee +[voTEE.oasis.io]: https://votee.oasis.io +[siwe-example]: https://github.com/oasisprotocol/demo-starter/tree/matevz/sapphire-paratime-2.0 +[onchain-signer]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/onchain-signer +[playground.oasis.io]: https://playground.oasis.io diff --git a/docs/guide.mdx b/docs/guide.mdx deleted file mode 100644 index 7fe58204..00000000 --- a/docs/guide.mdx +++ /dev/null @@ -1,291 +0,0 @@ ---- -description: Guide to creating secure dApps on Sapphire ---- - -import DocCard from '@theme/DocCard'; -import {findSidebarItem} from '@site/src/sidebarUtils'; - -# Guide - -This page mainly describes the differences between Sapphire and Ethereum -since there are a number of excellent tutorials on developing for Ethereum. -If you don't know where to begin, the [Hardhat tutorial] and the -[Solidity docs] are great places to start. You can continue following this -guide once you've set up your development environment and have deployed your -contract to a non-confidential EVM network (e.g. Sepolia). - - -[Hardhat tutorial]: https://hardhat.org/tutorial -[Solidity docs]: https://docs.soliditylang.org/en/v0.8.15/solidity-by-example.html - -## Oasis Consensus Layer and Sapphire ParaTime - -The Oasis Network consists of the consensus layer and a number of ParaTimes. -ParaTimes are independent replicated state machines that settle transactions -using the consensus layer (to learn more, check the [Oasis Network -Overview][overview chapter]). Sapphire is a ParaTime which implements the -Ethereum Virtual Machine (EVM). - -The minimum and also expected block time in Sapphire is **6 seconds**. Any -Sapphire transaction will require at least this amount of time to be executed, -and probably no more. - -ParaTimes, Sapphire included, are not allowed to directly access your tokens -stored in consensus layer accounts. You will need to _deposit_ tokens from your -consensus account to Sapphire. Consult the [Manage your -Tokens][how-to-deposit-rose] chapter to learn more. - - -[overview chapter]: https://github.com/oasisprotocol/docs/blob/main/docs/general/oasis-network/README.mdx -[how-to-deposit-rose]: https://github.com/oasisprotocol/docs/blob/main/docs/general/manage-tokens/README.mdx#rose-and-the-paratimes -[Testnet faucet]: https://faucet.testnet.oasis.io/ - -## Testnet and Mainnet - -Sapphire is deployed on Testnet and Mainnet chains. Testnet should be -considered unstable software and may also have its state wiped at any time. As -the name implies, only use Testnet for testing unless you're testing how -angry your users get when state is wiped. - -:::danger Never deploy production services on Testnet - -Because Testnet state can be wiped in the future, you should **never** deploy a -production service on Testnet! Just don't do it! - -Also note that while Testnet does use proper TEEs, due to experimental -software and different security parameters, **confidentiality of Sapphire on -Testnet is not guaranteed** -- all transactions and state published on the -Sapphire Testnet should be considered public. - -::: - -:::tip - -For testing purposes, visit our [Testnet faucet] to obtain some TEST which you -can then use on the Sapphire Testnet to pay for gas fees. The faucet supports -sending TEST both to your consensus layer address or to your address inside the -ParaTime. - -::: - -[network-parameters]: https://github.com/oasisprotocol/docs/blob/main/docs/node/mainnet/README.md -[Testnet]: https://github.com/oasisprotocol/docs/blob/main/docs/node/testnet/README.md - -## Localnet - -For development and testing, you can run a local [instance][localnet] of the -entire Sapphire stack. - -[localnet]: https://github.com/oasisprotocol/docs/blob/main/docs/dapp/tools/localnet.mdx - -## Sapphire vs Ethereum - -Sapphire is generally compatible with Ethereum, the EVM, and all the user and -developer tooling that you are used to. In addition to confidentiality -features, you get a few extra benefits including the ability to **generate -private entropy**, and **make signatures on-chain**. An example of a dApp that -uses both is an HSM contract that generates an Ethereum wallet and signs -transactions sent to it via transactions. - -There are also a few breaking changes compared to Ethereum though, but we think -that you'll quickly grasp them: - -- [Encrypted Contract State](#encrypted-contract-state) -- [End-to-End Encrypted Transactions and Calls](#end-to-end-encrypted-transactions-and-calls) -- [`from` Address is Zero for Unsigned Calls](#from-address-is-zero-for-unsigned-calls) -- [Override `receive` and `fallback` when Funding the Contract](#override-receive-and-fallback-when-funding-the-contract) -- [Instant Finality](#instant-finality) - -Read below to learn more about them. Otherwise, Sapphire is like Emerald, a -fast, cheap Ethereum. - -### Encrypted Contract State - -The contract state is only visible to the contract that wrote it. With respect -to the contract API, it's as if all state variables are declared as `private`, -but with the further restriction that not even full nodes can read the values. -Public or access-controlled values are provided instead through explicit -getters. - -Calling `eth_getStorageAt()` will return zero. - -### End-to-End Encrypted Transactions and Calls - -Transactions and calls are end-to-end encrypted into the contract. Only the -caller and the contract can see the data sent to/received from the ParaTime. -This ends up defeating some utility of block explorers, however. - -The status of the transaction is public and so are the error code, the revert -message and logs (emitted events). - -### `from` Address is Zero for Unsigned Calls - -The `from` address using of calls is derived from a signature attached to the -call. Unsigned calls have their sender set to the zero address. This allows -contract authors to write getters that release secrets to authenticated callers -(e.g. by checking the `msg.sender` value), but without requiring a transaction -to be posted on-chain. - -### Override `receive` and `fallback` when Funding the Contract - -In Ethereum, you can fund a contract by sending Ether along the transaction in -two ways: - -1. a transaction must call a *payable* function in the contract, or -2. not calling any specific function (i.e. empty *calldata*). In this case, - the payable `receive()` and/or `fallback()` functions need to be defined in - the contract. If no such functions exist, the transaction will revert. - -The behavior described above is the same in Sapphire when using EVM transactions -to fund a contract. - -However, the Oasis Network also uses [Oasis-native transactions] such as a -deposit to a ParaTime account or a transfer. In this case, **you will be able to -fund the contract's account even though the contract may not implement payable -`receive()` or `fallback()`!** Or, if these functions do exist, **they will not -be triggered**. You can send such Oasis-native transactions by using the [Oasis -CLI] for example. - -[Oasis-native transactions]: https://github.com/oasisprotocol/docs/blob/main/docs/general/manage-tokens/README.mdx -[Oasis CLI]: https://github.com/oasisprotocol/cli/blob/master/docs/README.md - -### Instant Finality - -The Oasis Network is a proof of stake network where 2/3+ of the validator nodes -need to verify each block in order to consider it final. However, in Ethereum -the signatures of those validator nodes can be submitted minutes after the block -is proposed, which makes the block proposal mechanism independent of the -validation, but adds uncertainty if and when will the proposed block actually be -finalized. - -In the Oasis Network, the 2/3+ of signatures need to be provided immediately -after the block is proposed and **the network will halt, until the required -number signatures are provided**. This means that you can rest assured that any -validated block is final. As a consequence, the cross-chain bridges are more -responsive yet safe on the Oasis Network. - -## Integrating Sapphire - -Once ROSE tokens are [deposited into Sapphire][how-to-deposit-rose], it should -be painless for users to begin using dApps. To achieve this ideal user -experience, we have to modify the dApp a little, but it's made simple by our -compatibility library, [@oasisprotocol/sapphire-paratime]. - -There are compatibility layers in other languages, which may be found in [the repo]. - -[@oasisprotocol/sapphire-paratime]: https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime -[the repo]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients - -## Writing Secure dApps - -### Wallets - -Sapphire is compatible with popular self-custodial wallets including MetaMask, -Ledger, Brave, and so forth. You can also use libraries like Ethers, Viem, and Wagmi -to create programmatic wallets. In general, if it generates secp256k1 signatures, -it'll work just fine. - -### Languages & Frameworks - -Sapphire is programmable using any language that targets the EVM, such as Solidity, -Fe 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 endpoints -[here](https://github.com/oasisprotocol/docs/blob/main/docs/dapp/sapphire/network.mdx#rpc-endpoints). - -### Transactions & Calls - - -![Client, Key Manager, Compute Node diagram](../../general/images/architecture/client-km-compute.svg) - -The figure above illustrates the flow of a **confidential smart contract -transaction** on Sapphire. - -Transactions and calls must be encrypted and signed for maximum security. -The [@oasisprotocol/sapphire-paratime] npm package will make your life -easy. It'll handle cryptography and signing for you. - -You should be aware that taking actions based on the value of private data may -**leak the private data through side channels** like time spent, gas use and -accessed memory locations. If you need to branch on private data, you should in -most cases ensure that both branches exhibit the same time/gas and storage -patterns. - -You can also make **confidential smart contract calls** on Sapphire. If you -use `msg.sender` for access control in your contract, the call **must be -signed**, otherwise `msg.sender` will be zeroed. On the other hand, set the -`from` address to all zeros, if you want to avoid annoying signature popups in -the user's wallet for calls that do not need to be signed. The JS library will -do this for you. - -:::note - -Inside the smart contract code, there is no way of knowing whether the -client's call data were originally encrypted or not. - -::: - -
- Detailed confidential smart contract transaction flow on Sapphire - -![Diagram of the detailed confidential smart contract transaction flow on Sapphire](diagrams/c10l-smart-contract-tx.mmd.svg) - -
- -
- Detailed confidential smart contract call flow on Sapphire - -![Diagram of the detailed confidential smart contract call flow on Sapphire](diagrams/c10l-smart-contract-call.mmd.svg) - -
- -### Contract State - -The Sapphire state model is like Ethereum's except for all state being encrypted -and not accessible to anyone except the contract. The contract, executing in an -active (attested) Oasis compute node is the only entity that can request its -state encryption key from the Oasis key manager. Both the keys and values of the -items stored in state are encrypted, but the **size of either is not hidden**. Your -app may need to pad state items to a constant length, or use other obfuscation. -Observers may also be able to infer computation based on storage access patterns, -so you may need to obfuscate that, too. See [Security chapter] for more -recommendations. - -[Security chapter]: ./security.md#storage-access-patterns - -:::danger Contract state leaks a fine-grained access pattern - -Contract state is backed by an encrypted key-value store. However, the trace of -encrypted records is leaked to the compute node. As a concrete example, an ERC-20 -token transfer would leak which encrypted record is for the sender's account -balance and which is for the receiver's account balance. Such a token would be -traceable from sender address to receiver address. Obfuscating the storage access -patterns may be done by using an ORAM implementation. - -::: - -Contract state may be made available to third parties through logs/events, or -explicit getters. - -### Contract Logs - -Contract logs/events (e.g., those emitted by the Solidity `emit` keyword) -are exactly like Ethereum. Data contained in events is *not* encrypted. -Precompiled contracts are available to help you encrypt data that you can -then pack into an event, however. - -:::danger Unmodified contracts may leak state through logs - -Base contracts like those provided by OpenZeppelin often emit logs containing -private information. If you don't know they're doing that, you might undermine -the confidentiality of your state. As a concrete example, the ERC-20 spec -requires implementers to emit an `event Transfer(from, to, amount)`, which is -obviously problematic if you're writing a confidential token. What you can -do instead is fork that contract and remove the offending emissions. - -::: - -## See also - - - diff --git a/docs/network.mdx b/docs/network.mdx index 88b005b3..1403ef1a 100644 --- a/docs/network.mdx +++ b/docs/network.mdx @@ -15,9 +15,20 @@ import {AddSapphireToMetaMask as S, AddSapphireTestnetToMetaMask as ST} from '@s | Chain ID | Hex:`0x5afe`
Decimal: `23294` | Hex:`0x5aff`
Decimal: `23295` | Hex:`0x5afd`
Decimal: `23293` | | Tools | | [Testing token Faucet][faucet] | [Local development Docker image][localnet] | +:::danger Never deploy production services on Testnet + +Because Testnet state can be wiped in the future, you should **never** deploy a +production service on Testnet! Just don't do it! + +Also note that while Testnet does use proper TEEs, due to experimental +software and different security parameters, **confidentiality of Sapphire on +Testnet is not guaranteed** -- all transactions and state published on the +Sapphire Testnet should be considered public. + +::: [faucet]: https://faucet.testnet.oasis.io/ -[localnet]: https://github.com/oasisprotocol/docs/blob/main/docs/dapp/tools/localnet.mdx +[localnet]: https://github.com/oasisprotocol/docs/blob/main/docs/build/tools/localnet.mdx ## RPC Endpoints @@ -62,7 +73,7 @@ dedicated RPC endpoints, consider the following providers (in alphabetic order): | Name (Provider) | Mainnet URL | Testnet URL | EIP-3091 compatible | |-----------------------------------------------|--------------------------------------------|--------------------------------------------|---------------------| -| Oasis Explorer ([Oasis Protocol Foundation]) | https://explorer.oasis.io/mainnet/sapphire | https://explorer.oasis.io/testnet/sapphire | Yes | +| Oasis Explorer ([Oasis Protocol Foundation]) | `https://explorer.oasis.io/mainnet/sapphire` | `https://explorer.oasis.io/testnet/sapphire` | Yes | | Oasis Scan ([Bit Cat]) | [https://www.oasisscan.com/paratimes/000…279](https://www.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000f80306c9858e7279) | [https://testnet.oasisscan.com/paratimes/000…f6c](https://testnet.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c) | No | [Bit Cat]: https://www.bitcat365.com/ diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index 234934ee..36368bb7 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -26,7 +26,7 @@ One simple-but-useful dApp that takes advantage of confidentiality is a data trove) if the operator fails to re-up before too long. Let's make it happen! -[higher level of security]: guide.mdx#writing-secure-dapps +[higher level of security]: ./build/README.mdx [dead person's switch]: https://en.wikipedia.org/wiki/Dead_man%27s_switch ### Init a new Hardhat project @@ -154,9 +154,9 @@ 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][social-media]. +Congratulations, you made it through the Sapphire tutorial! If you want to dive +deeper, please check out the [build] chapter and join the discussion on the +[#dev-central Discord channel][social-media]. Best of luck on your future forays into confidentiality! @@ -188,11 +188,11 @@ official [Oasis starter project for Go] and the [Oasis starter project for Pytho ## See also - + [social-media]: https://github.com/oasisprotocol/docs/blob/main/docs/get-involved/README.md#social-media-channels -[guide]: guide.mdx +[build]: ./build/README.mdx [hardhat-example]: https://github.com/oasisprotocol/sapphire-paratime/blob/stable/clients/js/1.x/examples/hardhat [`@oasisprotocol/sapphire-hardhat`]: https://www.npmjs.com/package/@oasisprotocol/sapphire-hardhat