Interacting with the Contract

Let’s recap what we’ve learned so far: Ethereum contracts are programs that control money, which run inside a virtual machine called the EVM. They are created by a special transaction that submits their bytecode to be recorded on the blockchain. Once they are created on the blockchain, they have an Ethereum address, just like wallets. Anytime someone sends a transaction to a contract address it causes the contract to run in the EVM, with the transaction as its input. Transactions sent to contract addresses may have ether or data or both. If they contain ether, it is “deposited” to the contract balance. If they contain data, the data can specify a named function in the contract and call it, passing arguments to the function.

Viewing the Contract Address in a Block Explorer

We now have a contract recorded on the blockchain, and we can see it has an Ethereum address. Let’s check it out in the ropsten.etherscan.io block explorer and see what a contract looks like. In the Remix IDE, copy the address of the contract by clicking the clipboard icon next to its name (see Copy the contract address from Remix).

Copy the contract address from Remix

Figure 17. Copy the contract address from Remix

Keep Remix open; we’ll come back to it again later. Now, navigate your browser to ropsten.etherscan.io and paste the address into the search box. You should see the contract’s Ethereum address history, as shown in View the Faucet contract address in the Etherscan block explorer.

View the Faucet contract address in the etherscan block explorer

Figure 18. View the Faucet contract address in the Etherscan block explorer

Funding the Contract

For now, the contract only has one transaction in its history: the contract creation transaction. As you can see, the contract also has no ether (zero balance). That’s because we didn’t send any ether to the contract in the creation transaction, even though we could have.

Our faucet needs funds! Our first project will be to use MetaMask to send ether to the contract. You should still have the address of the contract in your clipboard (if not, copy it again from Remix). Open MetaMask, and send 1 ether to it, exactly as you would to any other Ethereum address (see Send 1 ether to the contract address).

Interacting with the Contract - 图3

Figure 19. Send 1 ether to the contract address

In a minute, if you reload the Etherscan block explorer, it will show another transaction to the contract address and an updated balance of 1 ether.

Remember the unnamed default external payable function in our Faucet.sol code? It looked like this:

  1. receive () external payable {}

When you sent a transaction to the contract address, with no data specifying which function to call, it called this default function. Because we declared it as payable, it accepted and deposited the 1 ether into the contract’s account balance. Your transaction caused the contract to run in the EVM, updating its balance. You have funded your faucet!

Withdrawing from Our Contract

Next, let’s withdraw some funds from the faucet. To withdraw, we have to construct a transaction that calls the withdraw function and passes a withdraw_amount argument to it. To keep things simple for now, Remix will construct that transaction for us and MetaMask will present it for our approval.

Return to the Remix tab and look at the contract on the Run tab. You should see a orange box labeled withdraw with a field entry labeled uint256 withdraw_amount (see The withdraw function of Faucet.sol, in Remix).

The withdraw function of Faucet.sol, in Remix

Figure 20. The withdraw function of Faucet.sol, in Remix

This is the Remix interface to the contract. It allows us to construct transactions that call the functions defined in the contract. We will enter a withdraw_amount and click the withdraw button to generate the transaction.

First, let’s figure out the withdraw_amount. We want to try and withdraw 0.1 ether, which is the maximum amount allowed by our contract. Remember that all currency values in Ethereum are denominated in wei internally, and our withdraw function expects the withdraw_amount to be denominated in wei too. The amount we want is 0.1 ether, which is 100,000,000,000,000,000 wei (a 1 followed by 17 zeros).

Tip

Due to a limitation in JavaScript, a number as large as 10^17 cannot be processed by Remix. Instead, we enclose it in double quotes, to allow Remix to receive it as a string and manipulate it as a BigNumber. If we don’t enclose it in quotes, the Remix IDE will fail to process it and display “Error encoding arguments: Error: Assertion failed.”

Type “100000000000000000” (with the quotes) into the withdraw_amount box and click on the withdraw button (see Click “withdraw” in Remix to create a withdrawal transaction).

Interacting with the Contract - 图5

Figure 21. Click “withdraw” in Remix to create a withdrawal transaction

MetaMask will pop up a transaction window for you to approve. Click Confirm to send your withdrawal call to the contract (see MetaMask transaction to call the withdraw function).

MetaMask transaction to call the withdraw function

Figure 22. MetaMask transaction to call the withdraw function

Wait a minute and then reload the Etherscan block explorer to see the transaction reflected in the Faucet contract address history (see Etherscan shows the transaction calling the withdraw function).

Etherscan shows the transaction calling the withdraw function

Figure 23. Etherscan shows the transaction calling the withdraw function

We now see a new transaction with the contract address as the destination and a value of 0 ether. The contract balance has changed and is now 0.9 ether because it sent us 0.1 ether as requested. But we don’t see an “OUT” transaction in the contract address history.

Where’s the outgoing withdrawal? A new tab has appeared on the contract’s address history page, named Internal Transactions. Because the 0.1 ether transfer originated from the contract code, it is an internal transaction (also called a message). Click on that tab to see it (see Etherscan shows the internal transaction transferring ether out from the contract).

This “internal transaction” was sent by the contract in this line of code (from the withdraw function in Faucet.sol):

  1. msg.sender.transfer(withdraw_amount);

To recap: you sent a transaction from your MetaMask wallet that contained data instructions to call the withdraw function with a withdraw_amount argument of 0.1 ether. That transaction caused the contract to run inside the EVM. As the EVM ran the Faucet contract’s withdraw function, first it called the require function and validated that the requested amount was less than or equal to the maximum allowed withdrawal of 0.1 ether. Then it called the transfer function to send you the ether. Running the transfer function generated an internal transaction that deposited 0.1 ether into your wallet address, from the contract’s balance. That’s the one shown on the Internal Transactions tab in Etherscan.

Etherscan shows the internal transaction transferring ether out from the contract

Figure 24. Etherscan shows the internal transaction transferring ether out from the contract