Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
contract SplitFunds {
function split(address[] addrs){
if(!addrs[uint(block.blockhash(block.number-1)) % addrs.length].send(msg.value)) throw;
}
}
@tjade273
Owner

This simply uses the last blockhash to determine which of an array of addresses will get the value of the transaction. Since the blockhash will be different on each chain after the fork, chance of ending up with funds in the same account is 1/addrs.length.

This allows users to split their funds into a different account on each chain with high probability, disallowing any replay attack after the fork.

Users should simply broadcast a transaction to this contract on whichever network they are using, along with an array of 5-10 addresses that they control, not including the one they sent from. Thus, if the transaction is replayed on the other network, the funds on that chain will be securely in one of the other wallets. This can be verified by checking the balance of each account on both chains, and making sure different accounts recieved the funds. If not, simply repeat the procedure.

@emansipater

There's a simpler approach: just split based on whether or not the money is still in the darkDAO immediately after the fork block. Then you can actually choose which wallet gets forked and nonforked funds.

@D-Nice
D-Nice commented Jul 16, 2016

@emansipater haha, wish I used that in my contract from the get go, rather than checking the balance of the withdrawFunds contract.

@vessenes

This is awesome, thanks for publishing. I'm referencing it in my post here: http://vessenes.com/do-not-mess-with-eth-classic-it-will-f-you-up/. I think the odds of two slots getting the same funds are worse than you say, though -- I believe it's a 'birthday problem' -- when will n randomly chosen numbers be the same, given m possibilities? That makes the odds bad enough that I'd suggest the contract be instrumented to allow a re-send. I suppose you could just call it multiple times in this case.

As a side note, choosing the addresses may bear some thinking -- I recommended people use vanilla (not sequentially generated from the same private key) addresses for each 'slot'.

@veox
veox commented Jul 26, 2016 edited

I'm planning on using this technique in a dapp that'll reference my fork oracle for the condition check.

EDIT: Ah, I see there's already a splitter that uses Timon Rapp's oracle. No biggie.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment