The errors are related to conditions not satisfied, more specifically:
So I went back and undid the changes but its still not working and I dont know what Iâm missing, the error message isnt helping much but it says: [âŚ]
What function are you calling, what parameters are you sending?
Can you tell how to replicate it step by step?
Also I get one if I try depolying contract with an amount of ether:
If you are trying to send eth to your contract during the deployment you should make sure your constructor is payable otherwise the transaction will revert.
As @dan-i mention you about the conditions not being satisfied, i would like to add:
you have 2 require statements in your transfer function, you should add an error msg on them and try again, maybe one of those are being trigger. thats why you have a revert error probably.
I rewrote the contracts and theyre working fine now⌠I think it was because I wasnt updating the address of the government contract in code every time I deployed a new instance of it.
Yes, the Government contract address is different on each separate employment. Forgetting not to replace the previous address in your Bank contract for the new one is easily done. It catches most of us out the first time we make that mistake
This will have caused the transaction to revert (when you called the transfer function, right?) and will have given you the error message you got. The problem is that the error message you got was just a default one, and so thatâs why it wasnât helpful in pinpointing the error. Your error wasnât anything to do with the function not being marked payable, or the value exceeding the current balance.
@thecilâs advice, to always add an error message to your require() statements, is always a good idea, because if the revert is caused by one of them, the corresponding error message will appear as part of the error message you get in the Remix console. If one of those error messages doesnât appear, you then know that the transaction reverted because of something else.
Which line are you getting the error on and what does it say? There is nothing wrong with your mapping. But if you are using v0.8 instead of v0.7.5 then you need to make sure msg.sender is converted to a payable address in this line:
Before v0.8 msg.sender was payable by default, but unpayable by default from v0.8
I mention this, because your code throws an error for me on this line only.
OK, this is the 3rd attempt posting this reply to your âGovernment contract / payableâ issue LOL. I got myself in a muddle about one of the points I was explaining to you, but Iâve cleared it up now, and so rest assured you can rely on this post
If you saw either of the previous 2 posts (posted about 1.5 hours ago, then please ignore them. But Iâve deleted them now, so if this is the first reply youâre reading then great â you wonât have noticed anything strange
Easily done!
Whether youâre using v0.7 or v.0.8 any function which needs to receive ether needs to be payable
So here is the problem:
Your addTransaction function isnât payable in Government:
But you made this function payable in the interface in Bank:
The function is called with an ether value:
In the interface the function is payable, but the transaction will revert because the actual function being called in the external contract (Government) isnât payable.
You also need to make sure that all of your contracts related by inheritance are using the same Solidity version. Otherwise you will run into compatibility issues. You can still call the external Government contract, via the interface, if its v0.7, but it may be safer to use the same version there too. I have them all in the same version.
What I was saying earlier is that v0.8 requires msg.sender to be explicitly converted to a payable address if it is receiving ether. So in the Bank withdraw functionâŚ
⌠would need to be either âpayable(msg.sender).transfer(amount);
orâ owner.transfer(amount) if you have already made owner payable in Ownable (it will then still be payable in Bank due to inheritance). Wherever you have made a function onlyOwner, msg.sender can only be the owner address, so in these functions you can use owner or msg.sender interchangeably. You just need to be careful about when this address needs to be payable, and how you ensure it is payable.
If you use v0.7 then you wonât have this payable issue with msg.sender, because it is payable by default. On the other hand, owner would still need to be converted to a payable address if used to receive ether.
Also, this function wonât compile if the parameters donât maintain consistent names! They are without underscore in the header, but then with underscore when referenced in the function body.
that is exactly what this problem was thank you so much!
I did need to take an extra look at my headers after I do the video and complete the code. I usually catch those mistakes but did not in this instance so thank you!
value âused in â{value: 50 ether}â is not a property. This is syntax required by Solidity if you want to specifiy the amount of ether to be sent with an external function call. Here, the external function being called is addTransaction(). In this example, addTransaction() is called with the values input for the arguments: msg.sender (an address value), recipient (another address value), and amount (an unsigned integer value). Here, Iâm using the word value in a general sense. Note that the msg.sender as the 1st argument is not the sender of this function call. Instead it references the caller of the transfer() function (i.e. the sender of the funds being transferred). The addTransaction function is being called by the Bank contract, and so the value specified of 50 ether is effectively a payment made by the Bank contract to the Government contract. In order for the function call to be successful, the Bank contract must have a balance of at least 50 ether. If the function call is successful, the Bank contractâs ether balance will be reduced by 50 ether, and the Government contractâs balance increased by 50 ether. You can check this by adding a function to both contracts which gets the respective contract balances using: address(this).balance.
You can probably already see that a payment value of much less than 50 ether would probably be more appropriate!
So, having understood what {value: x ether/gwei/wei} does, we can now consider actual use cases.
In our Bank/Government contract example, the idea is that some kind of government levy or tax etc. is required to be paid by the bank (either itself, or on behalf of its account holders) for each transfer of funds between account holders. So, you can probably also see, now, why 1 gwei (= 1,000,000,000 wei, or 0.000000001 ether) would be a much more realistic value, considering the amounts of ether that are most probably being transferred.
The 3 arguments passed to the addTransaction function enable the Government contract to record each transaction (for which a payment/tax is due/paid) in its transaction log (the transactionLog array).
So thatâs the use case we are simulating in our example contracts. You can probably now appreciate that this type of value transfer between contracts could therefore be implemented whenever one contract needs to charge another contract for some kind of service or cost etc., or when it needs to receive an income from the other contract for a specific purpose, project etc. Our Government contract enables the government to generate income (raise taxes) from the economic activity of other contracts (here, banking activity). It could either be used by the bank to account for the payments it needs to make at a later date to the government (e.g. annually), or by the government itself to record and account for its income from bank transaction charges etc.
Iâve cut the following Government contract from your post in the Inheritance Assignment topic, and pasted it here. I know they are all one project, but I just want to avoid code and discussion involving the external Government contract appearing in a thread related to an earlier part of the course, where external contract instances, external function calls, and interfaces havenât been introduced yet.
My feedback on this particular contract is below your code.
Just a couple of other minor points to mention here:
You should be getting an orange warning in the compiler, indicating that you should restrict the getTransaction function to view. If a function doesnât need to change the contract state, itâs always safer to restrict it to view (so it can read the contract state, but not change it). Similarly if a function doesnât need to read or change the contract state, itâs safer to restrict it to pure.
Also in the getTransaction function, I would add names to the 2 address values returned, so that itâs clear which is the senderâs address and which is the recipientâs address.
When running the government contract I get the following error:
call to Government.getTransaction errored: VM error: invalid opcode. invalid opcode The execution might have thrown. Debug the transaction to get more information.
When I debug I it points to the getTansaction line
function getTransaction(uint _index) public view returns(address, address, uint) {
I have reviewed the video a few times and have the exact same code. I am not certain how to fix this error.
The functions in the parent contract with internal and public visibility are available for derived contracts, but not those with external or private visibility.
Q3
Yes⌠ââŚwhere a single parent contract is inherited by multiple different child contractsâŚâ
I assume you are trying to call getTransaction() from Remix, and not as an external function call from Bank, is that right? If I remember rightly, in the video only addTransaction() is included in the GovernmentInterface in Bank and then called externally from the Bank contract.
If thatâs the case, then one reason why you would get this error, is because you are calling getTransaction before having added a transaction i.e. if the transactionLog array is still empty.
transactionLog may be empty either because (i) addTransaction() hasnât been called from Remix, (ii) transfer() in Bank hasnât been called yet, meaning that addTransaction hasnât been called externally from within the transfer() function (which is the intended method of calling addTransaction and adding data to transactionLog). Or (iii) it could be due to an error related to the addTransaction function somewhere else in your Bank or Government code, meaning that calling addTransaction() itself fails.
**EDIT**
Before reading the rest of this post, jump to my next post, which I didnât realise until afterwards is more likely to be the issue. But, if not, then come back to the rest of this postâŚ
If your compiler is indicating an error with the lineâŚ
⌠then this could also be triggered by something in the function body, or even in the syntax at the end of your addTransaction function above. So, if the suggestions above (and below) donât help solve the problem, we would need to see your full code (both the Government and the Bank contract) to be able to identify the issue for you.
Other things that may be causing a problem (although I doubt it, considering the error you have described above):
If you are sure you have the exact same code, then the problem could be what is discussed in this post.
If addTransaction() is payable in the interface in Bank, but not in your Government contract. This function is called with an ether value and so needs to be payable in both, otherwise the transaction will revert.