Special Transaction: Contract Creation

One special case that we should mention is a transaction that creates a new contract on the blockchain, deploying it for future use. Contract creation transactions are sent to a special destination address called the zero address; the to field in a contract registration transaction contains the address 0x0. This address represents neither an EOA (there is no corresponding private–public key pair) nor a contract. It can never spend ether or initiate a transaction. It is only used as a destination, with the special meaning “create this contract.”

While the zero address is intended only for contract creation, it sometimes receives payments from various addresses. There are two explanations for this: either it is by accident, resulting in the loss of ether, or it is an intentional ether burn (deliberately destroying ether by sending it to an address from which it can never be spent). However, if you want to do an intentional ether burn, you should make your intention clear to the network and use the specially designated burn address instead:

  1. 0x000000000000000000000000000000000000dEaD
Warning

Any ether sent to the designated burn address will become unspendable and be lost forever.

A contract creation transaction need only contain a data payload that contains the compiled bytecode which will create the contract. The only effect of this transaction is to create the contract. You can include an ether amount in the value field if you want to set the new contract up with a starting balance, but that is entirely optional. If you send a value (ether) to the contract creation address without a data payload (no contract), then the effect is the same as sending to a burn address—there is no contract to credit, so the ether is lost.

As an example, we can create the Faucet.sol contract used in [intro_chapter] by manually creating a transaction to the zero address with the contract in the data payload. The contract needs to be compiled into a bytecode representation. This can be done with the Solidity compiler:

  1. $ solc --bin Faucet.sol
  2. Binary:
  3. 6060604052341561000f57600080fd5b60e58061001d6000396000f30060606040526004361060...

The same information can also be obtained from the Remix online compiler.

Now we can create the transaction:

  1. > src = web3.eth.accounts[0];
  2. > faucet_code = \
  3. "0x6060604052341561000f57600080fd5b60e58061001d6000396000f300606...f0029";
  4. > web3.eth.sendTransaction({from: src, to: 0, data: faucet_code, \
  5. gas: 113558, gasPrice: 200000000000});
  6. "0x7bcc327ae5d369f75b98c0d59037eec41d44dfae75447fd753d9f2db9439124b"

It is good practice to always specify a to parameter, even in the case of zero-address contract creation, because the cost of accidentally sending your ether to 0x0 and losing it forever is too great. You should also specify a gasPrice and gasLimit.

Once the contract is mined we can see it on the Etherscan block explorer, as shown in Etherscan showing the contract successfully mined.

Etherscan showing the contract successfully mined

Figure 5. Etherscan showing the contract successfully mined

We can look at the receipt of the transaction to get information about the contract:

  1. > web3.eth.getTransactionReceipt( \
  2. "0x7bcc327ae5d369f75b98c0d59037eec41d44dfae75447fd753d9f2db9439124b");
  3. {
  4. blockHash: "0x6fa7d8bf982490de6246875deb2c21e5f3665b4422089c060138fc3907a95bb2",
  5. blockNumber: 3105256,
  6. contractAddress: "0xb226270965b43373e98ffc6e2c7693c17e2cf40b",
  7. cumulativeGasUsed: 113558,
  8. from: "0x2a966a87db5913c1b22a59b0d8a11cc51c167a89",
  9. gasUsed: 113558,
  10. logs: [],
  11. logsBloom: \
  12. "0x00000000000000000000000000000000000000000000000000...00000",
  13. status: "0x1",
  14. to: null,
  15. transactionHash: \
  16. "0x7bcc327ae5d369f75b98c0d59037eec41d44dfae75447fd753d9f2db9439124b",
  17. transactionIndex: 0
  18. }

This includes the address of the contract, which we can use to send funds to and receive funds from the contract as shown in the previous section:

  1. > contract_address = "0xb226270965b43373e98ffc6e2c7693c17e2cf40b"
  2. > web3.eth.sendTransaction({from: src, to: contract_address, \
  3. value: web3.utils.toWei(0.1, "ether"), data: ""});
  4. "0x6ebf2e1fe95cc9c1fe2e1a0dc45678ccd127d374fdf145c5c8e6cd4ea2e6ca9f"
  5. > web3.eth.sendTransaction({from: src, to: contract_address, value: 0, data: \
  6. "0x2e1a7d4d000000000000000000000000000000000000000000000000002386f26fc10000"});
  7. "0x59836029e7ce43e92daf84313816ca31420a76a9a571b69e31ec4bf4b37cd16e"

After a while, both transactions are visible on Etherscan, as shown in Etherscan showing the transactions for sending and receiving funds.

Etherscan showing the transactions for sending and receiving funds

Figure 6. Etherscan showing the transactions for sending and receiving funds