We’ve sent ETH from our BitGo wallet to an exchange and they haven’t credited us yet — what’s going on?
This was a common customer question with a complex answer. Customers were not credited for transactions because exchanges don’t recognize Ethereum internal transactions sent from smart contracts.
The most concise explanation can be found here, from Ethereum core dev Nick Johnson:
Internal transactions, despite the name […] aren’t actual transactions, and aren’t included directly in the blockchain; they’re value transfers that were initiated by executing a contract. As such, they’re not stored explicitly anywhere: they’re the effects of running the transaction in question on the blockchain state.
When an exchange states that it “does not support smart contracts,” the exchange means that it does not support internal transactions. Since BitGo transactions originate from a multi-signature smart contract, the final recipient is not actually specified in the recipient field of the transaction, but is encoded in the smart contract function call. If an exchange is only looking at the recipient field, transactions of this type will be ignored and customers will not be credited.
• The transaction that reaches the recipient must be an external (not a smart contract) ETH transaction
• The transaction must maintain backwards compatibility with existing BitGo wallets (i.e. there should be no need to change our existing multisig contract)
• The transaction must maintain 2 / 3 multi-signature security
• The transaction must maintain signature accountability (i.e. it is possible to know which parties signed)
With the ETH still held inside the multi-signature smart contract, we can forward the amount we want to send to a hop address, and send it from that address to its final destination. We can ensure that the single-signature address only sends to the desired destination with an HSM-level policy and commitment signatures. Both the HSM and user sign the request destination and amount for verification before sending.