Inheritance & External Contracts - Discussion

Did you resolve this in the end?

You may find the errors are the following (but these may just be copy-and-paste mistakes in your post, and not errors in your code in Remix) …

(1)

The units of ether must be written in lower case letters i.e.

1 ether
1 gwei
1 wei

(2)

Your operator here is a dash, and not a minus sign. A dash is longer, and will throw a compiler error.

previousSenderBalance – amount // dash => incorrect syntax
previousSenderBalance - amount // minus sign => correct subtraction operator

If you look carefully you can just see the difference.


If these were just errors in your post, then post a full copy of your Bank contract, appropriately formatted as explained here, so that I can compile it myself and identify the issues.

Hi Filip,
In the Value calls tutorial. you have mentioned {value: 1 ether}. Please tell me why it is written 1 ether. can we write 2 ether, etc., and what does this value signify? Shouldn’t it be written as {value: amount ether} the amount that we want to transfer?
Thanks and regards.

1 Like

Hi @astro1,

Great questions!

Our particuar example code is based on a contractual relationship between a bank and the government. The idea is that the government needs to collect some kind of tax (or levy) on each banking transaction that is an internal bank 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. 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).

Instead of as a tax, another way to interpret this transfer of value between the two contracts could be as payment, or fees, 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.


Yes …

In Solidity, unsigned integers representing Ether values are equivalent to uints of wei e.g.

{value: 1000000000000000000}

/* A value call of 1000000000000000000 Wei  =  1000000000 Gwei  =  1 Ether

However, Solidity syntax also includes the suffixes ether and gwei , which provide us with a useful shorthand. For example, the following 3 alternatives are all equivalent to value calls of 1 ether …

{value: 1000000000000000000}
{value: 1000000000 gwei}
{value: 1 ether}

The suffix wei is also available, but this would only seem to be worth using in situations where there could be a risk of confusion, because the following 2 alternatives are both equivalent to value calls of 0.05 gwei …

{value: 50000000 wei}
{value: 50000000}

Here is a link to the relevant section in the Solidity documentation:
https://docs.soliditylang.org/en/latest/units-and-global-variables.html#ether-units

I’ve already partly answered this, above. The Ether value we are transferring to the Government contract is a payment made by Bank to Government in respect of the transfer of funds between two individual users of the Bank contract. The transfer itself is an internal transfer within Bank, and the amount value sent to Government is part of the data which will be added to the Government transaction log as a record of the transfer for which Bank has made a payment (of tax, or a fee for a service).

In any case, the suffixes ether, gwei and wei can only be used after literal numbers. You could reference an unsigned integer stored in a variable, but without the suffix e.g.

uint tax;

function transfer(address recipient, uint amount) public {
   // additional code
   governmentInstance.addTransaction{value: tax}(msg.sender, recipient, amount);
   // additional code
}

Just one final point… If you haven’t already, you’ll find it really helpful to add the following function to both the Bank and Government contracts. It enables you to retrieve the total contract address balance for each contract before and after specific transactions. This is useful for testing and for understanding the movements of Ether at a contract level.

function getContractBalance() public view returns(uint) {
    return address(this).balance;
}

Let me know if anything is unclear, or if you have any further questions :slight_smile:

Thanks Jon! Makes sense and see the error now.

1 Like

Thanks for the explanation with all this as it really clarified the intentions of the transfer and _transfer functions. Tbh I accidentally posted my question about transferFrom here when it was in fact a lesson from Eth Smart Contract Programming 201, “TokenStandards”. My bad, I’ve been going back and forth, occasionally going over old material and confused what lesson i was on. In any case, i will post that in the appropriate lesson so not to confuse anyone here because its not part of the lesson here. Either way this was helpful, thanks.

1 Like

Hey @Bitborn,

Ahhhh … OK that makes sense now :sweat_smile:
Not to worry … it’s great that you’re re-visiting earlier material, as you can often get more out of it, and discover things you didn’t notice before, after having aquired more technical knowledge and gained more practical experience :muscle:

Anyway, I’m glad the extra explanations were helpful :slight_smile:

Hey filip, I’m a bit confused on how value calls work. I would appreciate it if you could type a brief explanation or send an article. :grinning:

Hi @Adrian1,

I would suggest looking at this post, which first gives a detailed explanation of what the transfer() function itself is actually doing (point 1), and then goes on to explain how the external value call works within the context of the transfer() function’s operations (point 2). I think looking at this wider picture first will help you to identify what it is you have been missing, or have misunderstood, and is causing your confusion.

Then have a look at this post, which repeats some of the information in the first post, but also goes into detail about the different ways we can code the actual ETH value being transferred from one contract to another — using unsigned integers with or without the suffixes ether, gwei or wei; or by referencing an unsigned-integer value stored in a variable. This could help clear up any confusion relating to this particular aspect of the value call.

You can then let me know if there is still something specific that you don’t understand, and I’ll help you out with that :slight_smile:

Fkin legend with the government joke :smiley: Sadly exponentially more true today than 2 years ago.

What is the base contract?
The base contract is the contract we are extending a new contract from, its the parent contract.

Which functions are available for derived contracts?
All public and internal scoped functions.

What is hierarchical inheritance?
Is where a base contract serves as a parent contract for multiple contracts.

1 Like

Dear Filip and other friends of the academy,

I am doing the inheritance course.
I’ve made the bank contract (parent) and child contract (ownable), but when I try to deploy I can only pick ownable.sol while I have made two separate files of them.
Schermafbeelding 2022-02-28 om 16.46.38

Anyone know what’s wrong here?
All the code is as written by Filip in the courses and I was just able to deploy the bank contract before adding the ‘child’ ownable.

I am of course in the bank.sol contract when I try to deploy it.

Well today it all just works for some reason, didn’t change a thing, same browser and everything. :sweat_smile:
Back to the courses!

1 Like

Hi @DaanBoshoven,

Glad to hear you’ve managed to resolve the problem you were having, even though you’re not sure what the problem was in the first place! :sweat_smile:

I must admit, the fact that you say you haven’t changed anything is strange. Remix is known to misbehave sometimes, and when it does, closing everything down and exiting, and then reloading it again, can often resolve things, and this is maybe what has happened in your case.

Even if Bank.sol is open, it still might not appear in the contract field dropdown if it hasn’t compiled successfully: this could be due to errors in either Bank.sol itself or in any of its imported files and/or inherited contracts. But you can only deploy a contract if it has compiled without any errors; so the fact that you can now select it and deploy it without having made any changes, suggests that the issue you were having wasn’t the result of compilation errors.

Just to be clear: Bank should be the child contract (derived contract) which inherits Ownable (the parent, or base contract).

Looking forward to seeing your solution to the Inheritance assignment! If you have any more deployment issues, post your full code so I can copy-and-paste it into Remix and find out what the problem is.

By the way, don’t forget to also post your solutions to the earlier Events Assignment and Transfer Assignment …

Events Assignment https://studygroup.moralis.io/t/events-assignment/28040?u=jon_m
This is the assignment from the Events video lecture, which is near the end of the Additional Solidity Concepts section of the course.

Transfer Assignment https://studygroup.moralis.io/t/transfer-assignment/27368?u=jon_m
This is the assignment from the Payable Functions section of the course, where you have the task of completing the withdraw() function.

1 Like

Hey Jon, thanks for your reply!
Guess it was just a classic case of ‘computer says no’ :sweat_smile:.
It was all fine yesterday, been messing with the selfdestruct function, but at the end of the day it happened again.
Will try a different browser and see if that helps (currently using Chrome on MacOS).

I see I indeed forgot to post my solutions to the two assignments you mentioned.
Have done them both and written them down in my notebook (pen and paper, old skool :sunglasses:)
Will post the code on the forum as soon as I’m done messing with the selfdestruct function!

1 Like

I had the same problem. I saw it’s not happening to you anymore but in case you have it again, I solved it by saving the code (control “s”) of the contract I want to deploy and then it would switch to that file automatically

2 Likes

I am trying to deploy the government.sol file with the getBalance function that Filip talks about at the end of the video. This one:

getBalance function in government.sol
function getBalance() public view returns(uint){
        return address(this).balance;
    }

But when I deploy the government contract and just try the getTransaction function with index 0, I get an error and it throws revert saying:
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.

This also happens if I deploy both the government.sol and the bank.sol contracts, send a transfer on the bank contract and then look for the Transaction in the transactionLog in government.sol

Complete government.sol code
pragma solidity 0.8.7;

contract Government {

    struct Transaction {
        address from;
        address to;
        uint amount;
        uint txId;
    }

    Transaction[] transactionLog;

    function addTransaction(address _from, address _to, uint _amount) external payable {
        transactionLog.push(Transaction(_from, _to, _amount, transactionLog.length));
    }

    function getTransaction(uint _index) public view returns(address, address, uint) {
        return(transactionLog[_index].from, transactionLog[_index].to, transactionLog[_index].amount);
    }

    function getBalance() public view returns(uint){
        return address(this).balance;
    }

}

Did someone have the same problem? Not sure what is missing or why I’m getting the error.

Thanks for sharing that “fix” @santiago :ok_hand:

I’ve never had this problem, so I guess it must be due to a bug that only affects certain browsers/operating systems etc.

In my Remix, if the wrong file is showing in the contract field, I can just select the one I actually want to deploy from the dropdown, but all of the files in the inheritance structure are always included in the dropdown. But it sounds like the Bank contract isn’t/wasn’t even appearing in the dropdown for you and @DaanBoshoven :grimacing:

Anyway, thanks for sharing your workaround, as that may well help others if they experience the same issue. These things can be very frustrating when they just seem to randomly happen to you!

Hey @santiago,

If you only deploy your Government contract, and then call getTransaction() with any index value (including 0), but you do this before you have manually added any transaction data to the transactionLog array by calling addTransaction() with _to and _from addresses and an _amount … then you will get the error message you describe. This is a default error message, which usually isn’t helpful in pinpointing the actual error, which most probably isn’t anything to do with the function not being marked payable or the value exceeding the current balance. Instead, it looks like you’re getting this default error message because there is no Transaction struct instance in the array at that index position.

Having said that, however, the addTransaction() function only really has any meaning when called by an external function in another contract which is executing an actual transfer transaction of an amount between two addresses, and which supplies addTransaction() with these 3 pieces of data: sender’s address, recipient’s address, and transfer amount. So, getTransaction() in Government is only meant to be called after the Bank contract has performed at least one transfer transaction.

Have a look at this post, as this may well solve this issue, which is still giving you an error message even when you’ve called the transfer() function in Bank, which has then in turn called addTransaction() in Government. What could well be happening is what I describe in either (1) or (2), which are both caused by not changing the Government address assigned to your governmentInstance in Bank (which I explain at the beginning of this linked post).

Anyway, I hope that solves the problem. But if it doesn’t, post your full code (all contracts) and I’ll have a look to see if I can find what the problem is. I can’t immediately see any issues with your Government contract code, but debugging often requires reviewing, deploying and testing the full code.

1 Like

What is the base contract?
The base contract is known as the parent contract.
Which functions are available for derived contracts?
A derived contract can access all non private members including state variables and
internal methods.
What is hierarchical inheritance?
Hierarchical inheritance is similar to simple inheritance except a single contract acts as
a base contract for multiple derived contracts.

1 Like