uint storedData;
declares a state variable called storedData
of type uint
(unsigned integer of 256 bits). You can think of it as a single slot in a database that you can query and alter by calling functions of the code that manages the database. In this example, the contract defines the functions set
and get
that can be used to modify or retrieve the value of the variable.this.
prefix, you just access it directly via its name. Unlike in some other languages, omitting it is not just a matter of style, it results in a completely different way to access the member, but more on this later.set
again with a different value and overwrite your number, but the number is still stored in the history of the blockchain. Later, you will see how you can impose access restrictions so that only you can alter the number.address public minter;
declares a state variable of type address. The address
type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half of a keypair belonging to external accounts.public
automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. The code of the function generated by the compiler is equivalent to the following (ignore external
and view
for now):mapping (address => uint) public balances;
also creates a public state variable, but it is a more complex datatype. The mapping type maps addresses to unsigned integers.public
keyword is more complex in the case of a mapping. It looks like the following:event Sent(address from, address to, uint amount);
declares an “event”, which is emitted in the last line of the function send
. Ethereum clients such as web applications can listen for these events emitted on the blockchain without much cost. As soon as it is emitted, the listener receives the arguments from
, to
and amount
, which makes it possible to track transactions.Coin
contract object, and any user interface calls the automatically generated balances
function from above:msg
variable (together with tx
and block
) is a special global variable that contains properties which allow access to the blockchain. msg.sender
is always the address where the current (external) function call came from.mint
and send
.mint
function sends an amount of newly created coins to another address. The require function call defines conditions that reverts all changes if not met. In this example, require(msg.sender == minter);
ensures that only the creator of the contract can call mint
. In general, the creator can mint as many tokens as they like, but at some point, this will lead to a phenomenon called “overflow”. Note that because of the default Checked arithmetic, the transaction would revert if the expression balances[receiver] += amount;
overflows, i.e., when balances[receiver] + amount
in arbitrary precision arithmetic is larger than the maximum value of uint
(2**256 - 1
). This is also true for the statement balances[receiver] += amount;
in the function send
.require
function, but it also allows you to provide the name of an error and additional data which will be supplied to the caller (and eventually to the front-end application or block explorer) so that a failure can more easily be debugged or reacted upon.send
function can be used by anyone (who already has some of these coins) to send coins to anyone else. If the sender does not have enough coins to send, the if
condition evaluates to true. As a result, the revert
will cause the operation to fail while providing the sender with error details using the InsufficientBalance
error.1 ether
is 10**18 wei
) which can be modified by sending transactions that include Ether.null
), the transaction creates a new contract. As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the “nonce”). The payload of such a contract creation transaction is taken to be EVM bytecode and executed. The output data of this execution is permanently stored as the code of the contract. This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that returns that code when executed.gas_price * gas
up front from the sending account. If some gas is left after the execution, it is refunded to the creator in the same way.msg.sender
and msg.value
do not change their values.selfdestruct
operation. The remaining Ether stored at that address is sent to a designated target and then the storage and code is removed from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost.selfdestruct
, it is still part of the history of the blockchain and probably retained by most Ethereum nodes. So using selfdestruct
is not the same as deleting data from a hard disk.selfdestruct
, it can still perform that operation using delegatecall
or callcode
.