Smart Contracts – Why Are Outputs Different from Ordinary Transactions?

accountsexchangestransactions

A Coinbase exchange engineer said:

"Depositing from smart contracts is hard. Smart contract outputs are
not like normal ETH transactions and it is non-trivial for us to get
notified when we receive coins from smart contracts."

Similarly, the Bitfinex exchange says:

"At this time Bitfinex does not support Ethereum transactions
generated from smart contracts. To avoid missing deposits or deposit
delays ETH should only be sent in traditional transactions. If you are
uncertain that your deposit will not be sent as part of an Ethereum
contract execution, please find out for sure before sending your
deposit."

What is the technical difference between transactions generated by smart contracts and transactions generated by humans? Why is it harder to be notified when a coin is received from a smart contract (how would an exchange get notified when they receive coins from a human, and how would they get notified when they receive coins from a smart contract, and why is this different)? What was the motivation for this design choice by the Ethereum designers? Where can I go to read more details?

I skimmed https://github.com/ethereum/go-ethereum/wiki/Contracts-and-Transactions but did not see the answer there.

Best Answer

Here's an intuition. The simplest transaction in Ethereum costs 21000 gas and looks like this:

{from: '0x from', to: '0x to', value: web3.toWei(1, "ether")}

When you're depositing to the exchange, the exchange can watch for transactions that are sent to this deposit address. For example, for block 99 they could use web3.eth.getBlock(99, true, ...), and for each transaction object check if to equals the deposit address, and the value (amount of Ether in wei) that was sent. Relatively straightforward for the exchange to see what you've deposited.

But if you are using a contract to make a deposit, the to is no longer the deposit address that the exchange gave you. The to is the address of your contract, and in the transaction there will be an additional data field. This data provides instructions to the contract, to execute code, which may then transfer the Ether to the deposit address. The exchange has to also execute the code, if it wants to be sure that it received funds from such execution. (An exchange could use web3.eth.getBalance to monitor balances of deposit addresses, but if it wants to know exactly where the funds came from, it has to execute the code of all transactions.)

That's an overview and to read more, the Ethereum Wiki has links to other material such as the Yellow Paper, and White Paper. Reading this StackExchange for highly voted questions and answers, with tags like and is also helpful.

Technically, transactions are only initiated by humans: a contract invoking another contract is a message call (as defined in the Yellow Paper) not a transaction. Only the transaction is recorded on the blockchain because all further execution can be derived from the transaction.


For why withdrawing from an exchange to a contract wallet/account is not straightforward, it's because more gas is needed than the basic 21000 gas. Different contracts could consume different amounts of gas, and sufficient gas must be provided by the exchange otherwise the transaction does not take effect: the funds remain will remain with the exchange.

Related Topic