-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add snippets for storage I/O, ordering, and gas padding
- Loading branch information
Showing
2 changed files
with
115 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,116 @@ | ||
--- | ||
description: Security recommendations for Sapphire | ||
description: "Secure dApps: Recipes for Confidentiality" | ||
--- | ||
|
||
# Security | ||
|
||
Work in Progress | ||
This page is an ongoing work in progress to support confidential smart contract | ||
development. At the moment we address safeguarding storage variable access | ||
patterns and provide best practices for more secure orderings of error checking | ||
to prevent leaking contract state. | ||
|
||
## Storage Access Patterns | ||
|
||
You can use a tool such as [hardhat-tracer] to examine the base EVM state | ||
transitions under the hood. | ||
|
||
```shell npm2yarn | ||
npm install -D hardhat-tracer | ||
``` | ||
|
||
and add `hardhat-tracer` to your `config.ts` file, | ||
|
||
```typescript | ||
import "hardhat-tracer" | ||
``` | ||
|
||
in order to test and show call traces. | ||
|
||
```shell | ||
npx hardhat test --vvv --opcodes SSTORE,SLOAD | ||
``` | ||
|
||
You can also trace a particular transaction, once you know its hash. | ||
|
||
```shell | ||
npx hardhat trace --hash 0xTransactionHash | ||
``` | ||
|
||
For both [gas] usage and confidentiality purposes, we **recommend using | ||
non-unique data size**. E.g. 64-byte value will still be distinct from a | ||
128-byte value. | ||
|
||
:::caution Inference based on access patterns | ||
|
||
`SSTORE` keys from one transaction may be linked to `SLOAD` keys of another | ||
transaction. | ||
|
||
::: | ||
|
||
## Order of Operations | ||
|
||
When handling errors, gas usage patterns not only can reveal the code path | ||
taken, **but sometimes the balance of a user as well** (in the case of a diligent | ||
attacker using binary search). | ||
|
||
```solidity | ||
function transferFrom(address who, address to, uint amount) | ||
external | ||
{ | ||
require( balances[who] >= amount ); | ||
require( allowances[who][msg.sender] >= amount ); | ||
// ... | ||
} | ||
``` | ||
|
||
Modifying the order of error checking can prevent the accidental disclosure of | ||
balance information in the example above. | ||
|
||
```solidity | ||
function transferFrom(address who, address to, uint amount) | ||
external | ||
{ | ||
require( allowances[who][msg.sender] >= amount ); | ||
require( balances[who] >= amount ); | ||
// ... | ||
} | ||
``` | ||
|
||
## Gas Padding | ||
|
||
To prevent leaking information about a particular transaction, Sapphire | ||
provides a [precompile] for dApp developers to **pad the amount of gas used | ||
in a transaction**. | ||
|
||
```solidity | ||
contract GasExample { | ||
bytes32 tmp; | ||
function constantMath(bool doMath, uint128 padGasAmount) external { | ||
if (doMath) { | ||
bytes32 x; | ||
for (uint256 i = 0; i < 100; i++) { | ||
x = keccak256(abi.encodePacked(x, tmp)); | ||
} | ||
tmp = x; | ||
} | ||
Sapphire.padGas(padGasAmount); | ||
} | ||
} | ||
``` | ||
|
||
Both contract calls below should use the same amount of gas. Sapphire also | ||
provides the precompile to return the gas [used] by the current transaction. | ||
|
||
```typescript | ||
await contract.constantMath(true, 100000); | ||
await contract.constantMath(false, 100000); | ||
``` | ||
|
||
[gas]: https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html | ||
[hardhat-tracer]: https://www.npmjs.com/package/hardhat-tracer | ||
[precompile]: https://api.docs.oasis.io/sol/sapphire-contracts/contracts/Sapphire.sol/library.Sapphire.html#padgas | ||
[used]: https://api.docs.oasis.io/sol/sapphire-contracts/contracts/Sapphire.sol/library.Sapphire.html#gasused |