diff --git a/README.md b/README.md
index 0d42d4115..536b87084 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 b7db4857b..e8d36a168 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 dd04d4fd3..3093dacda 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 1a55d8c85..364cccd40 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 62247cf99..31235a832 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.mdx
+[Concepts]: ./develop/concept.mdx
-### Building on Sapphire
+### Develop 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 [develop] chapter.
+
+[develop]: ./develop/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/develop/README.mdx b/docs/develop/README.mdx
new file mode 100644
index 000000000..52d57629f
--- /dev/null
+++ b/docs/develop/README.mdx
@@ -0,0 +1,99 @@
+---
+description: Develop new dApps on Sapphire
+---
+
+# Develop
+
+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
+on the [Network information] page.
+
+[Network information]: ../network.mdx#rpc-endpoints
+
+### 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
+
+To connect your frontend to your smart contracts, see the [Browser] chapter.
+
+[Browser]: ./browser.md
+
+### More Frontend Frameworks
+
+We support the common frontend libraries with the v2 client:
+
+| Framework | Package | API Reference | GitHub |
+| ----------------------- | ------------------------------------------------- | ----------------- | ----------------------- |
+| **[Ethers v6][ethers]** | [@oasisprotocol/sapphire-ethers-v6][ethers-npmjs] | [API][ethers-api] | [GitHub][ethers-github] |
+| **[Viem][viem]** | [@oasisprotocol/sapphire-viem-v2][viem-npmjs] | [API][viem-api] | [GitHub][viem-github] |
+| **[Wagmi][wagmi]** | [@oasisprotocol/sapphire-wagmi-v2][wagmi-npmjs] | [API][wagmi-api] | [GitHub][wagmi-github] |
+
+[ethers]: https://docs.ethers.org/v6/
+[ethers-npmjs]: https://www.npmjs.com/package/@oasisprotocol/sapphire-ethers-v6
+[ethers-api]: https://api.docs.oasis.io/js/sapphire-ethers-v6
+[ethers-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/ethers-v6
+[viem]: https://viem.sh/
+[viem-npmjs]: https://www.npmjs.com/package/@oasisprotocol/sapphire-viem-v2
+[viem-api]: https://api.docs.oasis.io/js/sapphire-viem-v2
+[viem-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/viem-v2
+[wagmi]: https://wagmi.sh/
+[wagmi-npmjs]: https://www.npmjs.com/package/@oasisprotocol/sapphire-wagmi-v2
+[wagmi-api]: https://api.docs.oasis.io/js/sapphire-wagmi-v2
+[wagmi-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/integrations/wagmi-v2
+
+## Backend Development
+
+If you want to connect and execute transactions from your backend.
+Sapphire has three clients in different programming languages:
+
+| Language | Package | API Reference | GitHub |
+| --------------- | -------------------------------------------------- | ------------- | ------------------- |
+| **Javascript** | [@oasisprotocol/sapphire-paratime][sapphire-npmjs] | [API][js-api] | [GitHub][js-github] |
+| **Go** | [@oasisprotocol/sapphire-paratime][go-pkg] | [API][go-api] | [GitHub][go-github] |
+| **Python** | | [API][py-api] | [GitHub][py-github] |
+
+[sapphire-npmjs]: https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime
+[go-pkg]: https://pkg.go.dev/github.com/oasisprotocol/sapphire-paratime/clients/go
+[js-api]: https://api.docs.oasis.io/js/sapphire-paratime
+[go-api]: https://pkg.go.dev/github.com/oasisprotocol/sapphire-paratime/clients/go
+[py-api]: https://api.docs.oasis.io/py/sapphirepy/
+[js-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/js/README.md
+[go-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/go/README.md
+[Py-github]: https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients/py/README.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/develop/authentication.md
similarity index 99%
rename from docs/authentication.md
rename to docs/develop/authentication.md
index a4f61e01b..518d31c31 100644
--- a/docs/authentication.md
+++ b/docs/develop/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/develop/browser.md
similarity index 92%
rename from docs/browser.md
rename to docs/develop/browser.md
index a0ec76e15..18b3a018c 100644
--- a/docs/browser.md
+++ b/docs/develop/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/develop/concept.mdx b/docs/develop/concept.mdx
new file mode 100644
index 000000000..756d4ae11
--- /dev/null
+++ b/docs/develop/concept.mdx
@@ -0,0 +1,104 @@
+---
+description: Sapphire concepts
+---
+
+import DocCard from '@theme/DocCard';
+import {findSidebarItem} from '@site/src/sidebarUtils';
+
+# Concepts
+
+## 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.
+
+:::
+
+## See also
+
+
diff --git a/docs/deployment.md b/docs/develop/deployment.md
similarity index 100%
rename from docs/deployment.md
rename to docs/develop/deployment.md
diff --git a/docs/gasless.md b/docs/develop/gasless.md
similarity index 98%
rename from docs/gasless.md
rename to docs/develop/gasless.md
index 9a326b8bd..4e8bd5f53 100644
--- a/docs/gasless.md
+++ b/docs/develop/gasless.md
@@ -35,6 +35,7 @@ features such as the browser support are not fully implemented yet.
## On-Chain Signer
The on-chain signer is a smart contract which:
+
1. receives the user's transaction,
2. checks whether the transaction is valid,
3. wraps it into a meta-transaction (which includes paying for the transaction
@@ -44,7 +45,7 @@ The on-chain signer is a smart contract which:
The steps above are executed as a confidential read-only call. Finally, the user
then submits the obtained 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
@@ -271,7 +272,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
@@ -280,7 +280,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].
@@ -374,6 +374,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/security.md b/docs/develop/security.md
similarity index 100%
rename from docs/security.md
rename to docs/develop/security.md
diff --git a/docs/ethereum.mdx b/docs/ethereum.mdx
new file mode 100644
index 000000000..0ff8ce964
--- /dev/null
+++ b/docs/ethereum.mdx
@@ -0,0 +1,96 @@
+---
+description: Differences to Ethereum
+---
+
+import DocCard from '@theme/DocCard';
+import {findSidebarItem} from '@site/src/sidebarUtils';
+
+# 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.
+
+## See also
+
+
diff --git a/docs/examples.mdx b/docs/examples.mdx
new file mode 100644
index 000000000..a5fe9f7de
--- /dev/null
+++ b/docs/examples.mdx
@@ -0,0 +1,56 @@
+---
+description: Examples built with Sapphire
+---
+
+# Examples
+
+## Randomness
+
+
+
+ **[Oasis Swag Wheel][rng-example]** |
+ A dApp which uses onchain RNG to determine which Swag a participant wins |
+
+
+
+## Confidential Voting
+
+
+
+ **[VoTEE][votee-example]** |
+ Vote for the favorite Oasis mascot, see also [voTEE.oasis.io] |
+
+
+ **[Blockvote][voting-example]** |
+ General confidential and gasless voting, see also [vote.oasis.io] |
+
+
+
+## SIWE
+
+
+
+ **[SIWE authentication][siwe-example]** |
+ An dApp witch uses Sign in with Ethereum (SIWE) for authentication. |
+
+
+
+## Onchain signing
+
+
+
+ **[Onchain signing][onchain-signer]** |
+ An Example for Onchain transaction generation and signing |
+
+
+
+Find more examples, including the unofficial ones, 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 7fe58204c..000000000
--- 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 88b005b35..1403ef1a5 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 234934eec..88550bfb4 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]: ./develop/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 [develop] 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
+[develop]: ./develop/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
diff --git a/docs/testing.md b/docs/testing.md
new file mode 100644
index 000000000..bcf201bb8
--- /dev/null
+++ b/docs/testing.md
@@ -0,0 +1,127 @@
+---
+description: Testing on Sapphire
+---
+
+# Testing on Sapphire
+
+While Sapphire is EVM-compatible and you can use most EVM tools to build your
+dApp, but to test the confidential features you'll need to deploy and run the
+test on a network which supports it.
+
+Recommended networks for testing:
+
+1. Sapphire [Localnet]
+2. Sapphire [Testnet]
+
+## Local Development and Testing
+
+When you want a quick, iterative cycle for testing, the recommended approach is
+to run Sapphire on your local machine. Oasis provides a Docker container that
+simulates a local Sapphire blockchain—similar in spirit to a Hardhat Node or
+Ganache. This makes it easy to:
+
+- Spin up and tear down a local environment on-demand.
+- Interact with a local instance of the Sapphire ParaTime.
+- Debug your contracts thoroughly before heading to a live network.
+
+For details on setting up and running this local environment, check out the
+[Localnet] documentation from Oasis. It covers installation, configuration, and
+provides example commands to help you get started.
+
+### 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";
+
+// Example 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
+};
+```
+
+Running your tests locally would then be as simple as:
+
+```sh
+npx hardhat test --network sapphire-localnet
+```
+
+## Testing Encrypted Transactions
+
+One of Sapphire’s unique capability are encrypted transactions. To take full
+advantage of this during testing, you can use following provider:
+
+- Hardhat provider from `@oasisprotocol/sapphire-hardhat`
+- Ethers provider from `@oasisprotocol/sapphire-paratime`
+
+This custom provider automatically encrypts transactions, allowing you to test
+your contract’s confidential workflows in an environment that closely mirrors
+production on Oasis Sapphire.
+
+### Hardhat Provider
+
+The Hardhat provider is the recommended when working in a Hardhat setup
+
+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 title="hardhat.config.ts"
+// ESM
+import '@oasisprotocol/sapphire-hardhat';
+
+// CommonJS
+require('@oasisprotocol/sapphire-hardhat');
+
+/** All other plugins must go below this one! **/
+```
+
+After installation, simply write and run your tests and scripts as you normally
+would—your transactions will be automatically encrypted behind the scenes and
+you will see a green padlock for this transactions in the explorer.
+
+### Ethers
+
+To add the provider to your project, run:
+
+```shell npm2yarn
+ npm install -D @oasisprotocol/sapphire-paratime
+```
+
+Next, import the `wrap` function and wrap your ethers signer:
+
+```js
+import { wrap } from "@oasisprotocol/sapphire-paratime";
+
+const wallet = new Wallet(process.env.PRIVATE_KEY);
+const provider = new ethers.JsonRpcProvider('http://127.0.0.1:8545'); // Localnet RPC URL
+const wrappedSigner = wrap(wallet.connect(provider));
+```
+
+[Localnet]: https://github.com/oasisprotocol/docs/blob/main/docs/build/tools/localnet.mdx
+[Testnet]: ./network.mdx