Skip to content

Commit

Permalink
add random topics
Browse files Browse the repository at this point in the history
  • Loading branch information
lingyido committed Aug 19, 2024
1 parent f481e63 commit 4edead4
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
2 changes: 1 addition & 1 deletion index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Storing data securely on the blockchain is essential to maintain the integrity a

### [Random Data Integration](./random-security.md)

TODO
Integrating random data into smart contracts is a complex challenge, particularly on a deterministic blockchain. This article explores secure methods for generating and using random data in NEO N3 smart contracts, highlighting potential vulnerabilities and how to mitigate them.

### [Smart Contract Testing and Auditing](./testing-auditing.md)

Expand Down
95 changes: 92 additions & 3 deletions random-security.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,93 @@
# todo
# Random Data Integration in NEO N3 Smart Contracts

* revert-after-use
* side-channle like GAS manipulation
Random data is often necessary for functions like lotteries, gaming, and other applications that require unpredictability. However, generating random numbers securely on a deterministic blockchain like NEO N3 presents unique challenges. This article delves into the complexities of using random data in NEO N3 smart contracts, provides examples of common pitfalls, and offers strategies for ensuring randomness security.

## Understanding Random Data Integration in NEO N3

In traditional programming environments, random data can be generated using various algorithms and system calls. However, on a blockchain, all operations must be deterministic to ensure consensus among all nodes. This requirement makes secure random number generation particularly challenging, as any predictable or manipulable randomness can be exploited by malicious actors.

NEO N3 provides a built-in function, `System.Runtime.GetRandom`, which generates pseudo-random numbers. While convenient, its usage can be problematic if not properly handled, potentially leading to vulnerabilities.

## Notice the Specific Randomness Processing in NEO N3

When incorporating random data into your NEO N3 smart contract, it’s crucial to recognize the limitations and potential risks. Specifically, developers must ensure that random numbers cannot be predicted or manipulated by malicious users.

One common approach to generating random data is using the `System.Runtime.GetRandom` function. However, due to the deterministic nature of blockchain, this function's output can be influenced or predicted by other factors within the blockchain environment. Therefore, careful consideration is required when using this function in smart contracts, especially in scenarios like lotteries or other games of chance.

## Example Scenario: Simple Lottery with System.Runtime.GetRandom

Let's consider a straightforward lottery implementation where a random number determines if a prize is awarded. The contract generates a random number, and if the number is even, the user wins.

```csharp
public static void ExecuteLottery()
{
BigInteger randomNumber = Runtime.GetRandom();
if (randomNumber % 2 == 0)
{
// Award the prize
Transfer(GasToken.Hash, Runtime.ExecutingScriptHash, user, prizeAmount);
}
}
```

In this example, the contract directly uses `System.Runtime.GetRandom` to generate a number. While this approach is simple, it carries significant risks, as the randomness can be influenced by factors that are potentially predictable or manipulable by malicious actors.

## Mitigation Strategies

To secure random data integration in your NEO N3 smart contracts, consider the following mitigation strategies:

1. **Avoid Using Built-in Random Functions Directly**:
- Instead of relying on `System.Runtime.GetRandom`, use a more secure method, such as oracle or a two-step lottery process. In this approach, the contract first commits to a random number by storing the hash of a block or transaction. In a subsequent transaction, the contract uses the revealed block hash to determine the lottery outcome. This method leverages the unpredictability of block hashes, which are difficult to manipulate. Note, this is only an example for showing how commit-reveal works. Do not use this in practice cause relying only on `blockhash` is not good enough.

Example:
```csharp
// Commit phase: Store the block hash for the lottery (in transaction 1)
Storage.Put(Storage.CurrentContext, "lotteryCommit", Blockchain.GetHeight());

// Reveal phase: Use the stored block hash to determine the outcome (in transaction 2)
BigInteger blockHeight = (BigInteger)Storage.Get(Storage.CurrentContext, "lotteryCommit");
Block block = Ledger.GetBlock((uint)blockHeight);
BigInteger randomNumber = block.Hash.ToBigInteger();
if (randomNumber % 2 == 0)
{
// Award the prize
Transfer(GasToken.Hash, Runtime.ExecutingScriptHash, user, prizeAmount);
}
```

2. **Continue Using System.Runtime.GetRandom with Precautions**:
- If you must use `System.Runtime.GetRandom`, ensure strict checks and controls:
1. **Strictly Verify Entry Scripts**: Ensure that the user's entry script is verified to prevent any unauthorized code execution. Also, avoid any operations, especially transfers, that could trigger a callback or reentrancy, as highlighted in the reentrancy attack discussion.
2. **Control Gas Usage to Prevent Side-Channel Attacks**: Make sure the gas consumption is consistent across different execution paths. This prevents attackers from using gas consumption as a side-channel to deduce the randomness. Limiting the gas usage and ensuring that only profitable transactions are executed can help mitigate this risk.

```csharp
public static void ExecuteLotterySafely()
{
if (!Runtime.CheckWitness(user)) return;
BigInteger randomNumber = Runtime.GetRandom();

// Gas usage control logic
if (randomNumber % 2 == 0)
{
Runtime.BurnGas(100); // Ensure gas usage consistency
// Award the prize
Transfer(GasToken.Hash, Runtime.ExecutingScriptHash, user, prizeAmount);
}
else
{
Runtime.BurnGas(100); // Ensure gas usage consistency
}
}
```

## Conclusion

Integrating random data into NEO N3 smart contracts requires careful consideration to avoid potential vulnerabilities. By understanding the limitations of blockchain randomness and applying secure strategies, developers can protect their contracts from exploitation. Whether avoiding built-in random functions or implementing additional safeguards, its crucial to prioritize security in any application relying on randomness. There is always a balance between absolute fairness and efficiency; for simple tasks like selecting attributes for a commemorative NFT, the more user-friendly built-in randomness may suffice. However, when significant financial stakes are involved, no amount of security is too much.

## Further Reading

For more insights on smart contract security and random data integration in NEO N3, consider exploring the following resources:

- [NEO Core Developer's Paper Blockchain_Random_Number](https://github.com/Jim8y/jinghui.me/blob/master/content/publication/Blockchain_Random_Number%20(28).pdf)
- [Some NEO issues that may related](https://github.com/neo-project/neo/issues/2693)
- [How can I securely generate a random number in my smart contract?](https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract/83616#83616)

0 comments on commit 4edead4

Please sign in to comment.