Learn Solidity lesson 20. Address type methods.

João Paulo Morais
Coinmonks

--

The address type is one of the most used in Solidity, as it indicates accounts on the blockchain.

Every account has a balance in the base coin. In the case of the Ethereum network, an account has a balance in Ether. On other EVM-compatible blockchains, such as Polygon, the balance is in some native token of the network, such as MATIC for Polygon.

In Solidity, it is possible to retrieve coin/token balance information that an account has, from within a contract. This is done using the balance property of a variable of type address, as below.

address myAddress = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
myAddress.balance; // returns uint256

I’m using an address from an account created by Remix. The value myAddress.balance is of type uint256. We can also use an address literal expression to access the balance property, as below.

0x5B38Da6a701c568545dCfcB03FcB875f56beddC4.balance;

The account balance returns with its entire value, including all decimal places. In the case of Ethereum, the value returns in Wei.

A very common use is to check the account balance of the contract itself. In Solidity, there is the object this, which indicates the current contract instance. We can use this to retrieve the contract address, via address(this). So we can recover the balance of the contract.

address(this).balance;  // returns uint256

It is also possible to retrieve the contract bytecode using the code property, as below.

address(this).code;    // returns bytes

The code of a contract is a variable of type bytes. We can retrieve the bytecode of any contract through its address.

Sending Ether

We can send Ether (or the base coin/token of the blockchain) to any account on the network, from within contracts. There is more than one method to do this and we will see the difference between them.

The account that sends Ether from within a contract is the account for the contract itself, so it is necessary to have a positive balance in Ether to be able to send it.

It should be noted that only payable addresses have such methods. Attempting to invoke the (address).transfer method, for example, for an address that is not of type payable will throw an error.

If the address is not payable, it is possible to cast the variable, as below.

payable(address).(...);

transfer

The method transfer sends Ether to a given address. If while sending Ether an error occurs, the entire transaction is reverted. Let’s write a contract to send Ether with this method.

contract Addresses {   constructor() payable {}   function sendEther(address payable _address) public {
_address.transfer(10 ether);
}
}

We first send Ether to the contract at deploy time. For this you need to use the payable modifier in the constructor. To be able to receive value when invoked, functions must be of type payable. The constructor function is the one invoked at deploy time.

The amount of 10 Ethers will be sent to an account whose address is an argument of the function sendEther. Note that the function parameter is of type address payable, not just address. This is necessary to use the method transfer.

Solidity has 3 value units: wei, gwei and ether. In the above example we are using the unit ether.

One occurrence that can cause the method transfer to revert is the contract account does not have sufficient balance. Another possibility is to try to send Ether to a contract account that does not have a payable function.

The transfer method will revert if it encounters any errors.

send

Another possibility is to use the method send to send Ether to an account. Let’s see this in the statement below.

_address.send(10 ether);

The difference between transfer and send is that the send method does not revert on an error. It returns true/false if the sending is successful /failure.

It is possible (and almost always desirable) to test the return of the send method, as follows.

bool success = _address.send(10 ether);
if (!success) {
revert();
}

We haven’t studied all the ingredients of the code above, but let’s try to understand it. The method send returns true or false, depending on the success of sending Ether. In the example above, the return is assigned to the variable success.

Then we check if the variable success has the value of false, in the expression if (!success) (reads ‘’if not success’’). If it was not successful, we execute the method revert(), which reverts the transaction.

call

The method call is not only used to send Ether to a certain account, but also to interact with a certain contract account, being able to invoke functions. However, it is possible to use this method to only send Ether, as this is an option when sending a transaction to any account (either external or contract).

We’ll have a lot more to say about the method call in another lesson. For the moment, let’s just see how to use it to send Ether.

_address.call{value: 10 ether}("");

As the method call can invoke a contract function, it must returns two values: a generic value, which is the return of the executed function, and the information whether the transaction was successful or not.

This means that the call method returns a pair of values. The first return parameter is boolean, while the second is of type bytes. As we are only interested in knowing the success or failure of sending Ether, we can use the code below.

(bool success, ) = _address.call{value: 10 ether}("");

We just grab the information whether the Ether sending was a success or not, and ignore the other parameter.

Should I use transfer, send or call?

There is a difference that we need to know between using transfer, send and call. The first 2 methods only forward 2300 units of gas to the target account, which is just enough to carry out the Ether transfer. The call method forwards all available gas to the target account.

Let me explain. The purpose of the call method is much broader than just sending Ether. It will call a function in another contract, and it is not possible to know how much gas this function will require. Therefore, all available gas is forwarded.

Care must be taken when invoking functions from other contracts. They can use the forwarded gas to carry out malicious operations, including hacking the contract that sent the call. Not only this can be done as it was done in the exploit called reentrancy.

Until recently, it was recommended to use the transfer method to transfer Ether. The transfer method forwards only 2300 units of gas, in order to prevent the receiving account from using the available gas for some malicious attitude.

However, currently the recommended method is to use call. The idea is that the Ethereum gas table is flexible, and it may be that in the future to ship Ether will cost more than 2300 units of gas. This could somehow break a compatibility between versions.

Anyway, you need to understand the difference between these 3 methods and know how each one works.

Call, delegatecall and staticcall.

The method call is used to invoke functions in other contracts, but it is not the only option. It is possible to interact with other contracts in a simpler way through its interface, without using any of the methods described in this lesson.

Both the call method, as well as the methods delegatecall and staticcall are low-level, where it is necessary to explicitly encode the function and the arguments that will be sent.

The methods call and staticcall have many similarities, however delegatecall introduces some differences. It is mostly used to invoke functions in contracts that act as libraries.

The use of such methods is a more advanced subject and will be studied in more detail in a future lesson.

Thanks for reading!

Comments and suggestions about this article are welcome.

Any contribution is welcome. www.buymeacoffee.com/jpmorais

Join Coinmonks Telegram Channel and Youtube Channel learn about crypto trading and investing

Also, Read

--

--

João Paulo Morais
Coinmonks

Astrophysicist, full-stack developer, blockchain enthusiast. Unraveling cosmos mysteries by day, crafting the next Latin American novel by night.