Skip to content

Instantly share code, notes, and snippets.

@etscrivner
Last active January 29, 2017 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save etscrivner/33a94718f425c12f6321a0e3f4bc83dd to your computer and use it in GitHub Desktop.
Save etscrivner/33a94718f425c12f6321a0e3f4bc83dd to your computer and use it in GitHub Desktop.
Safe splitting contract that accounts for EIP-150 and ETH/ETC hard forks.
pragma solidity ^0.4.2;
contract EIP150ReplaySafeSplit {
// Fork oracle for EIP-150 fork
AmIOnEIP150Fork amIOnEIP150Fork = AmIOnEIP150Fork(/* To be deployed */);
// Fork oracle for ETH/ETC fork
AmIOnTheFork amIOnDAOFork = AmIOnTheFork(0x2bd2326c993dfaef84f696526064ff22eba5b362);
// This routine provides a way to route funds across Ethereum chain forks. It preserves
// the signature of split method from DAO hard-fork replay split contract. If the current
// blockchain is determined to be the Ethereum chain (EIP150 forked chain) then funds
// are sent to `ethTarget`. If the current chain is the ETC chain, then funds are sent to
// `etcTarget`. On the unforked EIP-150 chain funds are returned to sender.
//
// Params:
// ethTarget - The target address on the Ethereum blockchain.
// etcTarget - The target on the unforked DAO (Ethereum Classic) blockchain.
function split(address ethTarget, address etcTarget) returns(bool) {
return tripleSplit(ethTarget, etcTarget, msg.sender);
}
// This routine provides a way to route funds across three separate Ethereum forked chains.
// It first determines the current chain as one of: Forked EIP-150 chain, Unforked EIP-150 chain,
// or Ethereum Classic chain. Funds are then routed to the appropriate target for a given chain
// as follows:
//
// Params:
// ethTarget - Target on forked EIP-150 chain.
// etcTarget - Target on Ethereum Classic (DAO hard-fork) chain.
// unforkedEIP150Target - Target on unforked EIP-150 chain.
function tripleSplit(address ethTarget, address etcTarget, address unforkedEIP150Target) returns(bool) {
bool onEIP150Fork = amIOnEIP150Fork.forked();
bool onDAOFork = amIOnDAOFork.forked();
if (onEIP150Fork && !onDAOFork && ethTarget.send(msg.value)) {
return true;
} else if (!onEIP150Fork && onDAOFork && etcTarget.send(msg.value)) {
return true;
} else if (!onEIP150Fork && !onDAOFork && unforkedEIP150Target.send(msg.value)) {
return true;
}
// NOTE: We explicitly do not handle the (onEIP150Fork && onDAOFork) case
throw;
}
}
@jimpo
Copy link

jimpo commented Oct 15, 2016

I would change amIOnEtcFork to amIOnDAOFork for less ambiguity. EtcFork sounds like it could be a subsequent fork on the ETC chain.

Drop the fallback function.

Store the results of amIOnEip150Fork.forked() and amIOnEtcFork.forked() in local variables since I believe external contract calls cost more gas.

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