Which one of the two solutions is best depends on your security/usability trade-off. The later adds an additional authentication factor, but it also requires communicating a key over a secure channel, which is huge penalty in the usability field.

Terminable

Contract Owned often goes hand in with contract Terminable , also known as Mortal . This contract adds a function only owner can trigger, the function to permanently terminate the contract. Any Ether owned by the contract get send to the owner. It looks like this:

contract Terminable is Owned {

function terminate() external onlyOwner {

selfdestruct(owner);

}

}

This terminates the contract and sends any Ether held by the contract back to the owner. Easy-peasy. But! Ether is no longer the only currency in Ethereum. There are many tokens out there, and smart contracts can own tokens too. If you use the above terminate function on a contract that has tokens, those tokens are permanently lost!

Tokens, as a reminder, tend to have the following interface:

contract IERC20Basic {

function balanceOf(address who) constant public returns (uint);

function transfer(address to, uint value) public returns (bool ok);

event Transfer(address from, address to, uint value);

}

We can use these functions to send the tokens to owner on terminate :

function terminate(IERC20Basic[] tokens) external onlyOwner { // Transfer tokens to owner

for(uint i = 0; i < tokens.length; i++) {

uint256 balance = tokens[i].balanceOf(this);

tokens[i].transfer(owner, balance);

} // Transfer Ether to owner and terminate contract

selfdestruct(owner);

}

Now, we need to be really careful here! The innocent looking tokens[i].balanceOf(…) and tokens[i].transfer(…) are function calls to external contracts. This means they can fail or do nasty things like re-entering your contract!

Let’s consider failure first. Solidity bubbles the failures up the call stack, so when one of the calls fails, it will fail the entire terminate operation. This default behavior is not bad, we can inspect which token contract made us fail, exclude the misbehaving token and try again. You will not recover that token. This is fine; who wants to own a broken/malicious token anyway?

The terminate call can also fail when it runs out of gas. This puts an upper limit to the number of tokens types that can be recovered: at some point we reach the block gas limit. If your contract is going to own many different kinds of tokens, (for example an exchange) you need to come up with something better.

This leaves reentrancy. It is not a problem for our Terminable contract: onlyOwner prevents other contracts from calling the function. But this contract is not meant to be used on its own. When you inherit from Terminable and add external functions, remember that they can be indirectly called from the terminate function!

In general, don’t try to reclaim tokens you don’t trust. (This is a special case of the general lemma: don’t interact with contracts you don’t trust)