0

Hello World !

I'm trying to find a way to shuffle an array of addresses in Solidity !

Looking at Underscore / Lodash source code _.shuffle() points out a few things.

_.shuffle([1, 2, 3, 4]);
  * // => [4, 1, 3, 2]

Something like:

address[] public players;  
// Players addresses     -> 0x00001, 0x00001, 0x00002
// _.shuffle(players[]); -> 0x00002, 0x00001, 0x00001
// _.shuffle(players[]); -> 0x00001, 0x00002, 0x00001


EDIT with Example:

address[] public players;

function enter() public payable {
    require( msg.value >= .01 ether && msg.value % .01 ether == 0 );

    uint ticketCount = msg.value / .01 ether;
    for(uint i = 0; i < ticketCount; i++){
        players.push(msg.sender);
    }
}

function getPlayers() public view returns (address[]) {
    return players;
}

// Take this scenario, each ticket is worth 0.01 ether.
// Two players decide to play. One buys 3 tickets and the other 2 tickets.
// We push the first player address 3 times and 2 times into our players array.
// Player 1 address is duplicated 3 times, players 2 address is duplicated twice.
// In our players array there are a total of 5 addresses stored.

When we call the getPlayers() function after the players have deposited their ether we get:

0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,
0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,
0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,
0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB,
0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB,

I'm pretty sure this is a bad way to do it and might require extra gas to be spent. At the end of the game our players array of will reset but i'm sure that keeping logs about how much a player has deposited might be a better way to approach this matter. I still hope to find a better way than just moving most of the random logic on the of-chain and loose trust and security ...

Hope someone already has a better way !

  • 3
    it's better doing it at front end side (js) – Badr Bellaj Jul 10 '18 at 22:00
  • I'm hoping to remove centralization and don't want to choose the easy way ... – Liberalite Jul 11 '18 at 8:55
  • What is your question exactly, you want a unique list of players? Or do you want a random list of players? – rustyx Jul 11 '18 at 14:52
2

It's important to be weary of doing things on-chain that you don't need to, and shuffling an array is probably something that you need to think about, as it could get costly, and it's difficult to get true randomness on-chain.

If you want a shuffled array, but don't care about being truly random, (and assuming based on your code that players addresses get added by some action from the player), it probably makes more sense for the insertion to be randomised rather than shuffling a complete array.

Basically if you have an array

address[] public players;
// 0xAAA, 0xCCC, 0xBBB

And player 0xDDD wants to play, then you'd have

uint newPos = somePsuedoRandomFunction(); 
//newPos returns a number between 0 and players.length

If newPos == 4, then you'd just

players.push(`0xDDD`);

But if for example newPos == 1, you'd go

players.push(players[1]);
players[1] = 0xDDD;

That way you'd end up with a shuffled array, and the gas costs would be equally spread across each player.

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.