In the last few months, New Alchemy and others have recommended checking the length of message data (
msg.data for Solidity nerds) as a way to combat short data length attacks.
Our recommended fixes for this bug have included testing using the
< than operator, or alternately using
These are not equivalent. For FunFair, New Alchemy implemented this check with a
!=, but that was the wrong way to do it. We instrumented the Token contract for FunFair to be upgradable, but unfortunately, the FUN token address will need to be updated to fix this, because of some particulars about where the bug lies.
Currently FUN is trading at Bittrex, which uses New Alchemy-provided token wallets, and can work with FUN. However, groups or exchanges that use multi-signature wallets based on the Ethereum Foundation or Parity wallet will not be able to transfer FUN until this upgrade is completed.
https://funfair.io has more details about the next steps and will publish a transfer schedule. There should be a service interruption of less than 10 minutes on the specified day, and no balances will be affected.
We will take this opportunity to fix problems ethplorer and etherscan have showing some minted tokens as well.
Details on the problem
!= is bad has to do with the original short data length bug. When the
CALL opcode is used in the Ethereum Virtual Machine (EVM), there are few guarantees made about what the receiving function will do with the data.
In a decision that may or may not be considered good in a few years, the EVM pads out all data offered to an even integer multiple of 32-bytes. This is the origin of the message data length attack, creating cleverly short data that will be padded in bad ways.
However, solidity has a custom data format for calls. The first four bytes of any data passed to a solidity contract are used to look up the right spot in a jump table -- a directory of functions the contract provides. If there are no matches, the fallback function is used, a catch-all function that typically can receive ether.
So, for solidity,
call data is almost always 4 bytes plus the offered data. In the case of a transfer event, it’s 4 bytes + 32 bytes for the address + 32 bytes for the amount. The FUN token correctly checks that msg data length is 68 bytes in this case.
However, the foundation and parity multisignature wallets are more general. They are not used just for gatekeeping ERC20 transfers, but any function on the blockchain, and therefore they use the
CALL functionality to make a call with arbitrary data added.
These wallets store 68 bytes of data as a proposed call, and once approved issue the call. That call is padded to the nearest size acceptable by the EVM, 32*3 = 96 bytes, and issued.
At this moment, there is no data corruption -- an ERC20 contract will shift off the first 68 bytes and be happy. BUT, if the short data attack checker is checking for precisely 68 bytes, it will fail. Instead, the short data attack checker should only throw if data is less than 68 bytes.
This is the source of the bug we inadvertently incorporated into the FunFair token -- we checked
!=, and 96 does not equal 68. It is greater than 68 however, and the new version of the token checks only this inequality to stay compatible with the Parity and Ethereum Foundation wallets.