1

I know that the "how to generate random number" in solidity is a very common question. However, after reading the great majority of answers I did not find one to fit my case.

A short description of what I want to do is: I have a list of objects that each have a unique id, a number. I need to produce a list that contains 25% of those objects, randomly selected each time the function is called. The person calling the function cannot be depended on to provide input that will somehow influence predictably the resulting list.

The only answer I found that gives a secure random number was Here. However, it depends on input coming from the participants and it is meant to address a gambling scenario. I cannot use it in my implementation.

All other cases mention that the number generated is going to be predictable, and even some of those depend on a singular input to produce a single random number. Once again, does not help me.

Summarising, I need a function that will give me multiple, non-predictable, random numbers.

Thanks for any help.

1

Do you need these non-predictable numbers committed to the blockchain (e.g. because they determine a payment transaction), or synchronized between multiple users?

If no, then the answer given above will work. Randomness is generated from contract state using view function, which means you may as well off-load it to Javascript code calling on the client's computer, and then use Javascript's random number generator.

If you do need on-chain randomness and can wait until Ethereum 2.0 next year, there will supposedly be a non-predictable randomness function available through VDF (verifiable delay functions) or VRF (verifiable random functions), which would also be used in selecting the next validator for each block. https://our.status.im/two-point-oh-randomness/

0

You can use this pattern:

pragma solidity 0.4.26;

contract Test {
    uint256[] public globalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

    function getPartialArray() public view returns (uint256[] memory) {
        uint256[] memory localArray = clone(globalArray, globalArray.length);
        for (uint256 i = 0; i < localArray.length; i++) {
            uint256 n = i + uint256(keccak256(abi.encodePacked(msg.sender, now))) % (localArray.length - i);
            uint256 temp = localArray[n];
            localArray[n] = localArray[i];
            localArray[i] = temp;
        }
        return clone(localArray, localArray.length / 4);
    }

    function clone(uint256[] memory _array, uint256 _length) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](_length);
        for (uint256 i = 0; i < _length; i++) {
            array[i] = _array[i];
        }
        return array;
    }
}

Here is a short Truffle test to print some output (though it doesn't actually verify anything):

contract("test", accounts => {
    it("test", async () => {
        let test = await artifacts.require("Test").new();
        for (let i = 0; i < 100; i++) {
            const array = await test.getPartialArray({from: accounts[i % accounts.length]});
            console.log(array.join(", "));
        }
    });
});
  • This doesn't satisfy the non-predictable criterion set in the question. The random-generation is entirely deterministic, as now and msg.sender would both be available to any malicious contract intending to abuse the contract above. – AnAllergyToAnalogy Oct 3 '19 at 6:40
  • @AnAllergyToAnalogy: That's not possible by the definition of the blockchain (at least this blockchain), since everything is publicly viewable. – goodvibration Oct 3 '19 at 6:45
  • Exactly, so the answer to the question is that it's not doable in a single transaction. – AnAllergyToAnalogy Oct 3 '19 at 6:46
  • @AnAllergyToAnalogy: However, I believe that it actually does satisfy the specific use-case that this dude is trying to handle - some random sender who will call this function at some random time. Of course, one can generate the same numbers using that sender's address and the time at which he/she called the function. However, by the time this "malicious" user regenerates the same numbers, the original sender had already completed their activity (gambling or whatever). Of course, it's hard to tell without knowing the exact use-case at hand, but I've got a feeling that this is the intention. – goodvibration Oct 3 '19 at 6:48
  • It was specified in the question that the function be non-predictable. I assumed the person calling the function was the potential attacker. I would just create a contract that has a duplicate function, looks at the result, and then if it's favourable, executes the function on your contract, if not, it reverts. – AnAllergyToAnalogy Oct 3 '19 at 6:53
0

It isn't possible to generate non-predictable numbers in a single transaction in Solidity. Any data that would be used to generate the random number would be available to an attacker immediately before the transaction, and therefore the outcome could be known before the attacker chooses to act.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.