Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JeffreyBPetersen/9b7972799a756cfb72278b00e33900f3 to your computer and use it in GitHub Desktop.
Save JeffreyBPetersen/9b7972799a756cfb72278b00e33900f3 to your computer and use it in GitHub Desktop.
Contract to protect against replay attacks after the current Ethereum fork
contract PermanentDAOHardforkConditionalTransfer {
/* whether this contract is currently being used on the forked chain, it defaults to false */
bool public forked;
/* whether the value of "forked" has been set and locked yet, it defaults to false */
bool public readyAndLocked;
/* record the status of the fork and mark this contract ready to be used for transfers */
function setForkedAndLock(){
/* if the hardfork hasn't occured yet or has already been recorded by this contract, then throw an error instead of continuing */
if(block.number < 1920000 || readyAndLocked) throw;
/*
check whether this contract is currently operating on the forked chain and permanently record the result
the check is done by checking the balance of the contract to which funds are being moved by the hardfork
*/
forked = address(0xbf4ed7b27f1d666546e30d74d50d173d20bca754).balance > 1000000 ether;
/* block all future attempts to call this function */
readyAndLocked = true;
}
/* transfers the provided amount of ETH to "to" if "forked" is true */
function transferIfForked(address to) {
/* block transfers until the fork status has been recorded */
if(!readyAndLocked) throw;
if (forked)
/*
transfer control and all sent ETH to "to", typical accounts will immediately return control, contracts may execute additional logic in response
.call is used in place of .send in order to not limit gas usage if a default function is called when the ETH is received
the return value of .call is checked to avoid any cases in which ETH could potentially get stuck in this contract
*/
if(!to.call.value(msg.value)()) throw;
else
/* same as above but to the original sender instead of "to" */
if(!msg.sender.call.value(msg.value)()) throw;
}
/* same as above with an added ! (not) when checking whether "forked" was set to true when this contract was initialized */
function transferIfNotForked(address to) {
if(!readyAndLocked) throw;
if (!forked)
if(!to.call.value(msg.value)()) throw;
else
if(!msg.sender.call.value(msg.value)()) throw;
}
}
@JeffreyBPetersen
Copy link
Author

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