The Ethereum blockchain will be hard-forked this coming Tuesday on block 2463000 with the main changes being the gas repricing of opcodes (EIP 150 version 1c). A concerned redditor asked There is over $12,000 USD in this contract! Please can somebody tell me what the chances of it being able to be withdrawn after the hardfork are?….
EtherDelta is a decentralised ether and ERC20 token exchange – I’ll have to try using it some day. There is not much trading activity on the exchange at the moment.
Following is a screenshot of EtherDelta running in the Mist browser, loaded from https://etherdelta.github.io and you can find the guides here:

Let’s have a look at the EtherDelta source code at 0x4aea7cf559f67cedcad07e12ae6bc00f07e8cf65:
//last compiled with soljson-v0.3.6-2016-08-29-b8060c5.js
contract SafeMath {
//internals
function safeMul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function safeSub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function safeAdd(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c>=a && c>=b);
return c;
}
function assert(bool assertion) internal {
if (!assertion) throw;
}
}
contract Token {
/// @return total amount of tokens
function totalSupply() constant returns (uint256 supply) {}
/// @param _owner The address from which the balance will be retrieved
/// @return The balance
function balanceOf(address _owner) constant returns (uint256 balance) {}
/// @notice send `_value` token to `_to` from `msg.sender`
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transfer(address _to, uint256 _value) returns (bool success) {}
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _from The address of the sender
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
/// @notice `msg.sender` approves `_addr` to spend `_value` tokens
/// @param _spender The address of the account able to transfer the tokens
/// @param _value The amount of wei to be approved for transfer
/// @return Whether the approval was successful or not
function approve(address _spender, uint256 _value) returns (bool success) {}
/// @param _owner The address of the account owning tokens
/// @param _spender The address of the account able to transfer the tokens
/// @return Amount of remaining tokens allowed to spent
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
uint public decimals;
string public name;
}
contract StandardToken is Token {
function transfer(address _to, uint256 _value) returns (bool success) {
//Default assumes totalSupply can't be over max (2^256 - 1).
//If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
//Replace the if with this one instead.
if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
//if (balances[msg.sender] >= _value && _value > 0) {
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
} else { return false; }
}
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
//same as above. Replace this line with the following if you want to protect against wrapping uints.
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
//if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
} else { return false; }
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
mapping(address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 public totalSupply;
}
contract ReserveToken is StandardToken, SafeMath {
address public minter;
function ReserveToken() {
minter = msg.sender;
}
function create(address account, uint amount) {
if (msg.sender != minter) throw;
balances[account] = safeAdd(balances[account], amount);
totalSupply = safeAdd(totalSupply, amount);
}
function destroy(address account, uint amount) {
if (msg.sender != minter) throw;
if (balances[account] < amount) throw;
balances[account] = safeSub(balances[account], amount);
totalSupply = safeSub(totalSupply, amount);
}
}
contract EtherDelta is SafeMath {
mapping (address => mapping (address => uint)) tokens; //mapping of token addresses to mapping of account balances
//ether balances are held in the token=0 account
mapping (bytes32 => uint) orderFills;
address public feeAccount;
uint public feeMake; //percentage times (1 ether)
uint public feeTake; //percentage times (1 ether)
event Order(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s);
event Cancel(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s);
event Trade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, address get, address give);
event Deposit(address token, address user, uint amount, uint balance);
event Withdraw(address token, address user, uint amount, uint balance);
function EtherDelta(address feeAccount_, uint feeMake_, uint feeTake_) {
feeAccount = feeAccount_;
feeMake = feeMake_;
feeTake = feeTake_;
}
function() {
throw;
}
function deposit() {
tokens[0][msg.sender] = safeAdd(tokens[0][msg.sender], msg.value);
Deposit(0, msg.sender, msg.value, tokens[0][msg.sender]);
}
function withdraw(uint amount) {
if (msg.value>0) throw;
if (tokens[0][msg.sender] < amount) throw;
tokens[0][msg.sender] = safeSub(tokens[0][msg.sender], amount);
if (!msg.sender.call.value(amount)()) throw;
Withdraw(0, msg.sender, amount, tokens[0][msg.sender]);
}
function depositToken(address token, uint amount) {
//remember to call Token(address).approve(this, amount) or this contract will not be able to do the transfer on your behalf.
if (msg.value>0 || token==0) throw;
if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
tokens[token][msg.sender] = safeAdd(tokens[token][msg.sender], amount);
Deposit(token, msg.sender, amount, tokens[token][msg.sender]);
}
function withdrawToken(address token, uint amount) {
if (msg.value>0 || token==0) throw;
if (tokens[token][msg.sender] < amount) throw;
tokens[token][msg.sender] = safeSub(tokens[token][msg.sender], amount);
if (!Token(token).transfer(msg.sender, amount)) throw;
Withdraw(token, msg.sender, amount, tokens[token][msg.sender]);
}
function balanceOf(address token, address user) constant returns (uint) {
return tokens[token][user];
}
function order(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, uint8 v, bytes32 r, bytes32 s) {
if (msg.value>0) throw;
Order(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, msg.sender, v, r, s);
}
function trade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s, uint amount) {
//amount is in amountGet terms
if (msg.value>0) throw;
bytes32 hash = sha256(tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
if (!(
ecrecover(hash,v,r,s) == user &&
block.number <= expires &&
safeAdd(orderFills[hash], amount) <= amountGet &&
tokens[tokenGet][msg.sender] >= amount &&
tokens[tokenGive][user] >= safeMul(amountGive, amount) / amountGet
)) throw;
tokens[tokenGet][msg.sender] = safeSub(tokens[tokenGet][msg.sender], amount);
tokens[tokenGet][user] = safeAdd(tokens[tokenGet][user], safeMul(amount, ((1 ether) - feeMake)) / (1 ether));
tokens[tokenGet][feeAccount] = safeAdd(tokens[tokenGet][feeAccount], safeMul(amount, feeMake) / (1 ether));
tokens[tokenGive][user] = safeSub(tokens[tokenGive][user], safeMul(amountGive, amount) / amountGet);
tokens[tokenGive][msg.sender] = safeAdd(tokens[tokenGive][msg.sender], safeMul(safeMul(((1 ether) - feeTake), amountGive), amount) / amountGet / (1 ether));
tokens[tokenGive][feeAccount] = safeAdd(tokens[tokenGive][feeAccount], safeMul(safeMul(feeTake, amountGive), amount) / amountGet / (1 ether));
orderFills[hash] = safeAdd(orderFills[hash], amount);
Trade(tokenGet, amount, tokenGive, amountGive * amount / amountGet, user, msg.sender);
}
function testTrade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s, uint amount, address sender) constant returns(bool) {
if (!(
tokens[tokenGet][sender] >= amount &&
availableVolume(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, user, v, r, s) >= amount
)) return false;
return true;
}
function availableVolume(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s) constant returns(uint) {
bytes32 hash = sha256(tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
if (!(
ecrecover(hash,v,r,s) == user &&
block.number <= expires
)) return 0;
uint available1 = safeSub(amountGet, orderFills[hash]);
uint available2 = safeMul(tokens[tokenGive][user], amountGet) / amountGive;
if (available1<available2) return available1;
return available2;
}
function cancelOrder(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, uint8 v, bytes32 r, bytes32 s) {
if (msg.value>0) throw;
bytes32 hash = sha256(tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
if (ecrecover(hash,v,r,s) != msg.sender) throw;
orderFills[hash] = amountGet;
Cancel(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, msg.sender, v, r, s);
}
}
The main concern would be the msg.sender.call.value(amount)() call in the withdraw(...) method. From a brief look at this method, there should be no problems with withdrawing the ethers from this contract. Gas cost for the call function would increase by 660, if the message sender is a regular externally owned account. If the message sender is a smart contract (wallet contract), some opcodes in this wallet contract may raise the amount of gas required for a successful send. The transaction sent to the withdraw(...) method of this contract just has to increase the supplied gas by this amount.
This contract withdrawal should be safe from this hard-fork change.
Relevant to this question is A quick note on how the CALL gas cost increase will affect contracts.