Hi @atlwarrior,
Our particular example is based on a contractual relationship between a government and a bank. The idea is that the government needs to collect some kind of tax on each banking transaction that is a transfer. To keep things simple in our example, the government is collecting a fixed amount of tax on each transfer. I would suggest an amount much smaller than 1 ether would be more appropriate, for example any value from 1 wei up to 1 gwei. This amount (which is the amount of tax paid by the Bank, and not the amount transferred from one bank account holder to another) will be automatically transferred from the Bank contract balance to the Government contract balance on each successfully executed transfer transaction.
When an amount of ether (always in units of wei) is sent from one contractâs address balance to an external contractâs address balance, the ether itself is not passed to the external function executing this transaction in the same way as other arguments are. For example, if our Bank contract was only sending 1 gwei to the Government contract, but no other data was being sent as arguments to be processed within the external function receiving the value transfer, our external function call, and the external function itself, could look something like thisâŚ
// within one of the Bank contract's functions
governmentInstance.collectTax{value: 1 gwei}();
// within the Government contract
function collectTax() external payable { }
Now, letâs return to our example of the government collecting tax on each banking transaction that is a transfer. For record keeping purposes, the relevant data for each transfer is also sent from Bank to Government and stored in the governmentâs transaction log (an array). The data sent is passed to the external function as 3 arguments. The 3rd argument (amount
) references the amount being transferred between two Bank contract account holders. The other two arguments reference the addresses of the two participants in the transfer â the sender and the recipient.
It is important to realise that the amount
argument does not represent an amount of ether entering or leaving the Bank contract when transfer() is called. The amount
is just an internal accounting adjustment to the balances in the mapping of the two individual account holders participating in the transfer (the sender and the recipient). The adjustments to their respective balances in the mapping reflect the change in each individualâs share of the total contract address balance and, therefore, the change to what each individual is entitled to withdraw from the contract. The total amount of ether held in the Bank contract does not actually change as a result of the amount transferred between the sender and recipient addresses (the amount
argument). The only change in the Bank contractâs address balance is a reduction for the tax payment transferred between the two contract addresses.
In the Government contract, the amount
parameter together with the senderâs address and the recipientâs address are pushed to the transaction log as part of a transaction instance created within the addTransaction() function from the Transaction struct. The amount of wei received as the tax payment is automatically added to the Government contract address balance, and this could be checked by adding the following function to your Government contract, and then calling it after a transfer has been executed:
function getContractBalance() external view returns(uint) {
return address(this).balance;
}
The same function could also be added to the Bank contract, so that you can also check that the same amount of wei (sent as the tax payment) has been deducted from the Bank contract address balance.
Instead of as a tax, another way to interpret this transfer of value between the two contracts could be as payment for some kind of record keeping service i.e. the Bank contract pays the Government contract for storing all of its transaction data.
However we interpret this payment from one contract to the other, it demonstrates (albeit in an overly simplistic way) how we can program automatic interactions between individual contracts for the purposes of both data and value transfer. Hopefully, this example shows the potential for these sorts of programmed interactions to be applied to many different use cases.
And hopefully this explanation has helped to clarify the difference between a transfer of value in wei using the curly brackets, and a transfer of data as arguments/parameters within the parentheses. But do let me know if anything is still unclear, or if you have any further questions about value calls