Deeper Analysis of 0xBTC Token Contract Code
It is important to be able to reason that a particular ERC20 token’s codebase is secure, or if it is vulnerable. Here is the way that I analyze the 0xBTC token to ensure that the contract is secure. First, lets check out the diff of the contract versus a known-safe ERC20 token contract, the one on the Ethereum Wiki.
Ethereum Wiki ERC20 Template: https://theethereum.wiki/w/index.php/ERC20_Token_Standard (scroll to bottom)
0xBTC Token Code: https://raw.githubusercontent.com/0xbitcoin/0xbitcoin-token/master/contracts/_0xBitcoinToken.sol OR https://etherscan.io/address/0xb6ed7644c69416d67b522e20bc294a9a9b405b31
First, please make sure you read the Diff, the differences between the two codebases. Here is what is different:
- Comments and names , no affect
- ExtendedMath library is added to give the limitLessThan method (used in _reAdjustDifficulty)
- Events are given the ‘emit’ keyword, no affect
- balanceOf() & allowance() return a constant instead of a view; no affect
- New static constant integers are instantiated in the 0xBTC contract contructor, not a possible security hole
And then on to all that matters:
6. A mint() method is added which is publicly callable and which creates new tokens!
7. A _startNewMiningEpoch method and a _reAdjustDifficulty method are added but these are only callable internally and thus not a possible vulnerability
Therefore, it can be reasoned that the only non-standard code that we need to be concerned about auditing is the mint() method and then the internal methods it calls, _startNewMiningEpoch and _reAdjustDifficulty. Since mint() is the only new public method and since it will revert if it is not given a valid new PoW solution, its attack surface is extremely limited.
For those wondering about the method transferAnyERC20Token(), as you can see it was directly copied from the sample ERC20 token contract on the Official Ethereum Wiki. It is the only method that can only be called by the Owner, and it only allows the owner to Transfer() out tokens that reside inside the smart contract to another address. The way the Transfer() is implemented in 0xBTC is right here:
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
emit Transfer(msg.sender, to, tokens);
Transfer(msg.sender, to, tokens);
return true;
}
The .sub and .add methods are safemath and so cannot overflow, cannot create new tokens.
As you can see, the way this method is delegate-called, the 0xBTC contract address will be the ‘msg.sender’ and so it will only allow the owner to transfer tokens whose ‘address’ in the balance mapping is equal to the address of the 0xBTC contract.
This means that the only tokens that can be ‘transferred’ are ones which have been explicitly sent directly to the 0xBTC contract address (or as we say, ‘sent into the contract’) after they have been mined using Proof of Work. This is because the contract address will be msg.sender since that is how delegate calling works: https://ethereum.stackexchange.com/questions/21029/difference-between-msg-owner-and-msg-sender
The intent of the method as designed is to allow the owner of the contract to withdraw tokens which had been accidentally sent into the contract address. That is all it can do. It was used for that and worked well!
For brevity and extra peace of mind, the 0xBTC contract is now owned by a burn contract: https://etherscan.io/address/0x9c875cd04abfa2bd0461c9baf42059913f6e7150