Weak Randomness

Defining Weak Randomness

Weak randomness occurs as the randomization of data such as generating a random number in a smart contract. It is a hard problem to solve as many developers are tempted to often use a predictable data chain for the random number. This data chain could take in values such as block number, block hash, and block timestamp which are all incredibly valuable to the overall security of a blockchain application. All of these values are able to be manipulated by miners hence why it is such a poor way to generate random digits. Possible solutions are to use a secure RNG for smart contracts such as RANDAO or RBGC

Popular Solutions Available:

Block Hashing or Timestamp

Randomness plays a pivotal role in many different types of smart contracts and necessary for others. One of the simpler approaches to creating a “random” number is to use a random number already generated within the smart contract via block hashing or timestamp. This seems to be the most widely used form of random number generation following under the assumption that the hash or time minded can be manipulated. Despite this being the most popular method, it is often times one of the most vulnerable. This vulnerability can be exploited by drawing the timestamps, thus giving someone like a miner access to edit the timestamp to be favorable every single time to their liking.

Oracles

Another commonly used random number generation is through the use of Oracles. Smart contracts are only to be in contact with the block chain itself, however Oracles are a third-party software that can allow access to outside sources as well as right from outside sources. This outside source is selected from the oracle owner and thus is only as reliable as the owners themselves, giving them the power to report that any given number is “random.” This could be considered centralizing the process of selecting a random number.

Commitment Scheme

A verifiably secure method of generating a random number in a smart contract is using a commitment scheme. In this approach there will be multiple participants within a contract that can create a random number together. Each member will create their own one random number, then sending the hash of the random number to the smart contract. Then the contract checks each hash to make sure that all instances are correct. The major security feature is that each of the hash’s are very difficult to change or manipulate data without the entirety of the contract members allowing it to be changed. This is not an efficient form of security however, as there it requires all contract members to stay in continuous contact with one another. Additionally, it does not always provide the same level of randomness under the assumption that one person may just use the same number every single contract instead of actively choosing a random digit.

RANDAO

The problem of interaction is solved with a smart contract called RANDAO. This is a contract that provides other contracts with random numbers using a participant-based system that requires volunteers to interact with RANDAO in a similar way as the commitment scheme to create a random number. This system, however, is not what it seems as there is much malpractice that causes its vulnerability to be more than desirable. The biggest concern is that certain random hashes are reused multiple times for separate contracts. Additionally, just like Oracle, the system can only be as secure as the owner and the trust of the anonymous people creating these numbers.

Demonstration of Attack:

This is the WeakRandomness contract. It is a simple guessing the number game to win a prize. In this case the prize is one Ether. Firstly, a constructor is created with the payable attribute that allows for funds to be put into the contract. Next we have a function titled "rng" for "random number generator" with a guess value being input. The answer is being input with a generated "random" number. This number is created from within the smart contract by calling the previous blockhash and using it as a source of randomness for the generated number. This blockhash is a very poor source of randomness and thus the weak randomness within this contract. After the function is a simple if statement giving the reward if the guess is the same as the number

This is the AttackPoint contract. its an explotative contract that will call the same previous blockhash as the guessing game smart contract. Next it will allow for the funds to be received and "steal" the funds from the game. The way it does this is through calling the exact same blockhash and thus ALWAYS producing the same "random" number that the WeakRandomness contract does. There is another function getBalance that is used to check the balance of the attack point account.

Demonstration of Solution:

This file only contains one contract and that is to generate a random number. This is the VRFv2Consumer contract which imports from the chainlink GitHub the necessary files to interact with the LINK tokens, VRF Coordinators and with the functions that actually will generate the numbers. The variables that depend on the test network are the VRF Coordinator to know which network to use, the link token id for that network, and the key hash for the amount of Gwei per hash. For the Goleri Test Network I used these were the values, however they may change depending on the network. Next, the callbackGasLimit variable is used for limiting gas usage during callback transactions with the requestConfirmations and numWords variables setting the checks and the amount of number generated. The last three variables each are for the constructor and functions to hold values created.

This is in the same VRFv2Consumer contract that was shown above. The constructor takes in the subscription ID which is then checked to make sure that there is an active subscription. The COORDINATOR variable is given its value and the LINKTOKEN variable is set to what type of link will be used, which are both based on the network as well. The s_owner and s_subscription ID are given the values of their respective variables setting the owner and setting the subscription ID. The functions fufilRandomWords and RequestRandomWords work together to request a random number and giving all of the variables to generate a random number and then fulfilling that request by sending that random number to an array of numbers the size of the numWords variable.

Why Use Chainlink?

Chainlink is a more recent addition to the current Oracles that can be used to generate a random number. In fact the V2 of the VRFconsumerBase.sol is a very recent addition and comes with many features that present the best reliability and function for generating a truly random number.

So why was chainlink used for this project? As shown Block Hashing is not a true source of randomness and is too exploitable to be considered a good way to generate any type of number. Using a Commitment Scheme Is a verifiably secure source, but can come with some massive downsides such as the timing it takes to actually generate said random number being the longest out of every other method as well as the possibility of a user in the contract being untruthful. RANDAO is seen to be the second most popular choice when it comes to generating a random number, however it was not used because of the many different security issues that arise with the package itself, such as sources of randomness being fixed and the reuse of randomly generated numbers an unfavorable amount.

This leaves us with an Oracle method, however oracles themselves are not perfect. Where chainlink differs is many of the functions have built in checks that can be implimented. These checks will ensure that it is ONLY the contract owner requesting a random number such that there is no way to obtain the number that is generated unless it is the owner. Additionally there are checks to verify that the number that is generated from chainlink is indeed random, which will result in any generated number to truly be a random result. Lastly the owner can request multiple random numbers that will be stored in an array of numbers and given to the owner such that all or one of the many numbers generateed can be used. These three features create a system that is vastly ahead of any other Oracle currently available.

How To Run Attack:


WRA.mp4

What Deploying Attack Contracts Should Look Like:

This is the order in which to deploy the contracts and see how it looks for information on how to set up and run the code please watch the video above. The pictures above are in order from left to right with the picture to the left of this text being the transactions.

  1. First, deploy the WeakRandomness contract on the ganache test network with the first account. Have a value of 1 Ether when deploying. In the second picture you can see the guessing game to guess the random number.

  2. Second, in a second account deploy the AttackPoint contract. Once deployed, copy the address of the WeakRandomness contract and past it into the steal function's address box. Do this by clicking the symbol of the file overlapping another file on the weak randomness contract.

  3. Lastly, click the steal function and watch the transaction complete and the Ether is transferred from one account to another.

How To Run Solution:


WRSc.mp4

What Deploying Solution Contracts Should Look Like:

This is the order in which to deploy the contracts and see how it looks for information on how to set up and run the code please watch the video above. The first picture is to the left of this text, and the pictures below this text go in order from left to right. Directly below this text are the transactions made.

  1. First, Using MetaMask on the goerli test network create a subscription on the VRF Subscription site and add some LINK TOKEN funds to the subscription. Confirm all transactions and it will give you an ID number

  2. Deploy the VRFv2Consumer contract using the ID created in the subscription ID box. For this demonstration my subscription ID was 7211. Accept all transactions and continue.

  3. Copy the address of the contract that was just deployed and go back to the VRF Subscription site and add the address as one of the consumers. Accept all transactions and continue.

  4. Click the requestRandomness function and accept all the transactions.

  5. Laslty click the s_requestId this will verify your ID and then return the randomly generated number.

References:

  1. Amiet, N. (2021). Blockchain vulnerabilities in practice. Digital Threats: Research and Practice, 2(2), 1–7. https://doi.org/10.1145/3407230


2.Chatterjee, K., Goharshady, A., & Pourdamghani, A. (2019, July 1). Probabilistic Smart Contracts: Secure randomness on the blockchain. IEEE Xplore. Retrieved from https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8751326

3. Chainlink. (2022). Subscription method: Chainlink documentation. Chainlink Developers. Retrieved from https://docs.chain.link/docs/vrf/v2/subscription/

4.YouTube. (2022). Exploring Chainlink Vrf v2 | Developer Walkthrough. YouTube. Retrieved from https://www.youtube.com/watch?v=rdJ5d8j1RCg.