Hi, I had a hard time finding what option/setting I can enable on Remix to get it to display variable values including âdecoded outputâ in the console log. Example for this is in video âConstructorsâ at 03:35. If you are in the same boat, go to the âHomeâ file, click âMoreâ, then activate your âDebuggerâ module. You may even need to reload the webpage for this to take full effect. Now when you run the program it will display a âDebugâ button on the bottom-right which you can toggle/open and it will show what youâre looking for⌠Phew!
yeah think the reason for this is the remix ui has changed a lot over the years since filip made the videos on this course. great that you found a solution tho
Filip created a âfromâ param in the private function â_transferâ instead of simply using âmsg.senderâ like he does in âtransferâ function (see screen shot). I tested using âmsg.senderâ in the private function â_transferâ as well and it works just fine so not getting why we would create a separate param for this. Any thoughts?
Hi! The compiler keeps stopping this program. I wrote it exactly like in the video, but the complier is not satified!
I get:
ParserError: Expected â(â but got identifier
â> HelloWorld.sol:18:14:
|
18 | function getBalance() public view returns (uint){
| ^^^^^^^^^^
on lines 18 and 19 I wrote:
function getBalance() public view returns (uint){
return balance[msg.sender];
Sincerely,
Aaron
There is a public function, which is transfer
that everyone can use, this function have hard coded that only the caller is able to transfer funds from himself to another (recipient).
While the internal function _transfer
is only accessible to the contract itself, no one can use it, and its the one that override the values of the balance mapping of the contract, basically it does the critical step, which is transfer funds.
Since this function does not contain any security measure, if you made it public, everyone will be able to transfer funds from everyone to any. Meaning, I could transfers funds from your wallet to mine.
Instead, the transfer
function is the only one that the public can use to made transfer, and its hard coded to allow the caller (msg.sender
) to transfer from his funds, to any.
Hope I explained myself clear, if not let me know
Carlos Z
Please share your code in the following way so i can review it properly
Carlos Z
Hi Carlos, thx for the reply!
Below is what I did and tested yesterday and since msg.sender is hard-coded in private function _transfer, itâs still only possible for the account invoking the smart contract to send funds to a recipient. Is the problem, perhaps, that on a real blockchain a private function thatâs not directly invoked doesnât know about msg.sender and this only works within Remix with fake accounts/addresses?
function transferAmt(address recepient, uint amt) public {
_transferAmt(recepient, amt);
}
function _transferAmt(address to, uint amt) private {
balance[msg.sender] -= amt;
balance[to] += amt;
}
Thx in advance!
Gabe
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
//// because we do ts w message sender,
// we cannot get balance of sone else, UNLESS WE CHANGE
// THE ADDRESS WHICH IS DOING THE SC ACTION!!
//if we change to another address, in the left section
// we do get other accounts & balances,
// the msg. sender
// is that address which is doing the SC action
//which, in remix is in the left section
contract Bank {
mapping(address => uint) balance;
function addBalance(uint _toAdd) public returns (uint){
balance[msg.sender] += _toAdd;
return balance[msg.sender];
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
//crypto is subtracted from person using the contract, msg.sender
//& is sent to receiver address by adding it to receiver's amount
//this program does not check about msg.sender's balance
//(to find out if there is enough crypto in his balance
//for this action)
function transfer(address receiver, uint amount) public {
_transfer(msg.sender, receiver, amount);
}
//from address is msg.sender
//receiver is an input
//amount is input for variable amount in function above
//the user calls the funtion above, because it a a public function,
//after that the private function is called
//this function can also be used again by other functions
//it seems that the program knows the from address as msg.sender
// from the order of the variables in ()
//How does Solidity know that the addition and subtraction of balance
//is for ETH? it is uint, but it does not say eth.
//is uint about address automatically a number for an amount of ETH?
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
The code works well. (I sent the code, and I also formatted it.)
I understand most or all of the Solidity instructions.
But there are some questions I have about it. 1. FROM and TO are used in the transaction, but how does Solidity know which address is FROM and which is TO? It is because the Solidity matches FROM and TO with the order / sequence of addresses in the arguments of the function above?
2 How does Solidity know that the amount to transfer is ETH. The input/argument is just a uint number. Is it because Solitity automatically connects uint amounts to ETH when one uses addresses, or the word âbalanceâ?
Also, the part of functions before { is called, in the lessons, âheaderâ. I would normally call this part of the structure a heading. Is it usual, with smart contracts, to call this part of the structure a âheaderâ? A header is usually the top part of a set of pages, where you can put things like the title of a book, page number, etc.
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
It will follow the order of logic stablished in the function body.
balance
in this contract, its a mapping that store a number (uint), using _transfer
will modify the values on the mapping. So far, we are not dealing with funds, further in the course you will understand the difference
Carlos Z
OK. I knew that this was not ETH, just numbers, but I pretend that it is ETH!
I looked at the instructions again, and it is very logical.
Also, I asked about the âheaderâ, which is the word that the teacher used in the video about the part of a function before â{â. A header is usually the top part of a set of pages, where you can put things like the title of a book, page number, etc.
I would normally call this part of the structure a âheadingâ:
function addBalance(uint _toAdd) public returns (uint)
before { ⌠}
Is âheaderâ the usual word for this part of a function?
Oh, ok, in terms of computer science, in programming, the term function header goes to the definition of the function.
Function Header:
function someName (arguments) [options]
Initialized with the keyword function
then you assign someName
to it, you specify if this function needs some arguments
(or not) and for Solidity, we also specify the options
(like private, public, modifiersâŚ).
Function Body:
The logic that the function execute inside {...}
.
function someName (arguments) [options]{
some logic...;
}
So taking as example the following function, we can define it like:
// FUNCTION HEADER
function _transfer(address from, address to, uint amount) private
// FUNCTION BODY
{
balance[from] -= amount;
balance[to] += amount;
}
Hope I explained myself clear, if not let me know
Carlos Z
Thank you for the explanation. It was very good.
That is a very good explanation. Thanks!
@thecil I tried the contracts with the bank and government, and they did not work. In fact, the bank could not even send transactions. I copied the code from what Filip put on Github, and it still did not work. If even the code given from the teacher as a solution does not work, that can be a difficult situation.
//SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
import "./Ownable.sol";
contract Bank is Ownable {
mapping(address => uint) balance;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
msg.sender.transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
type or paste code here
```![LIKE THE TEACHER'S CODE, BUT I GOT AN ERROR 2 SEPTEMBER 2022|690x332](upload://opMrhoEfXuR1EyT8r5ebmFl9wiz.png)
hey @ARK, your contract compiles fine for me. Im wondering could it be your Ownable/sol contract. this is the only thing i can verify. can you share your Ownable.sol contract. but i can confirm the code above its fine and works. Are you sure also that the compiler vsrsion your using in Remix matches the version your using for your codtract?
Remix sometimes adjusts the version of Solidity, in response to the contract. I seems to match or approximately match the contract version. I did notice that the teacherâs Ownable contract is actually called Owner. I can try to to change the contract name, and see if that solves the problem.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Owner {
address private owner;
// event for EVM logging
event OwnerSet(address indexed oldOwner, address indexed newOwner);
// modifier to check if caller is owner
modifier isOwner() {
// If the first argument of 'require' evaluates to 'false', execution terminates and all
// changes to the state and to Ether balances are reverted.
// This used to consume all gas in old EVM versions, but not anymore.
// It is often a good idea to use 'require' to check if functions are called correctly.
// As a second argument, you can also provide an explanation about what went wrong.
require(msg.sender == owner, "Caller is not owner");
_;
}
/**
* @dev Set contract deployer as owner
*/
constructor() {
console.log("Owner contract deployed by:", msg.sender);
owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor
emit OwnerSet(address(0), owner);
}
/**
* @dev Change owner
* @param newOwner address of new owner
*/
function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}
/**
* @dev Return owner address
* @return address of owner
*/
function getOwner() external view returns (address) {
return owner;
}
@mcgrane5 I solved the problem with the compiler and the interface (to the function in the Government contract). I needed to add and deploy the Government contract to Remix! But now the compiler is stopping the Bank contract about something else!
(upload://CGr7u04rMQ5Te0xMpMRC25JjMx.png)