What is the difference between msg.sender and from address in solidity smart contracts, are both the same who are initiating the transaction? - solidity

I am just starting out with the solidity and the smart contracts but i am confused like what is the difference between msg.sender and from address in ERC20 guidelines for the creation of smart contracts

msg.sender refers to the account that is calling the function it could be an EOA (Externally Owned Account) or a contract Address.
from is a parameter for the function.
Example:
// Send an amount from any address to any address
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
_transfer(from, to, amount);
return true;
}
// Send an amount from the function caller to any address
function transferFromCaller(address to, uint256 amount) public virtual override returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}

msg.sender is actually the address that you use when calling the function. This is a global variable that you don't define. As far as I understant, in a Token contract, "from" is the address of the account you want to use to spend some amount of token.

Related

Solidity: Internal or recursive type is not allowed for public state variables, Cannot Expose public mapping containing struct

I don't understand why this doesn't work when I can see it works in the existing bravo contracts
I'm trying to support inhertance of a public property I have structs that look like so:
abstract contract Governance {
struct Proposal {
/// #notice Unique id for looking up a proposal
uint id;
/// #notice Creator of the proposal
address proposer;
/// #notice the ordered list of target addresses for calls to be made
address[] targets;
/// #notice Receipts of ballots for the entire set of voters
mapping (address => Receipt) receipts;
//...
}
/// #notice Ballot receipt record for a voter
struct Receipt {
/// #notice Whether or not a vote has been cast
bool hasVoted;
/// #notice Whether or not the voter supports the proposal or abstains
uint8 support;
/// #notice The number of votes the voter had, which were cast
uint96 votes;
}
}
I'm trying to expose a public mapping like so:
mapping(uint256 => ProposalVote) public bravoProposals;
When I try to expose this I get an error:
TypeError: Internal or recursive type is not allowed for public state variables.
I'm using solidity 0.8.9? This should work, what am I missing here?
I'm not sure why this is the case, but it seems solidity can't expose public mapping whose do not start at a "definitive" point
By adding an arbitrary value with a definitive length, it can be exposed.
struct ProposalVote {
bool isTrue;
uint256[] votes;
mapping(address => bool) hasVoted;
}
Note: This answer is based on observations and I would prefer a better answer

Why is a retrieve function introduced here when the contract already provides this?

this is my first post and I am pretty new to programming and working my way through learning solidity with the help of freeCodeCamp on Youtube right now.
At around 1:48:00 in this video (https://www.youtube.com/watch?v=M576WGiDBdQ) the author introduces the retrieve function which basically has the same functionality of the statement in contract, right? When both of them lead to the same result, why would using the retrieve function be necessary in this case? Isn't this function just going to waste space? Or which advantages does it provide? Unfortunately he doesn't explain it and it's confusing me like hell.
Kind regards
contract SimpleStorage {
uint256 favoriteNumber;
function retrieve() public view returns (uint256) {
return favoriteNumber;
}
}
Storage variables default to internal visibility if you don't specify the visibility. So without that function you don't have a public getter for the variable.
You could remove the need for the view function by simply declaring the variable with public visibility:
uint256 public favoriteNumber;

Is there a way to check if msg.sender owns some collection?

Is there a way to do the following:
function registerCollection(address __collection) public {
require(msg.sender == IERC721(__collection).owner), "Does not own contract");
...[rest of function]...
}
Is there a way, within solidity, to access the owner field of another contract. So I do not mean owns an NFT of another collection, which could be done by calling .ownerOf(tokenId) and comparing to msg.sender. I want to get the actual owner of the contract.
It's possible that a collection has a address public owner, especially if it inherits from Openzeppelin's Ownable library.
So you are able to get it like this:
interface IOwnable {
function owner() external view returns(address)
}
IOwnable(__collection).owner()
Though be aware that if a collection doesn't gave a public owner the call will revert.

How to make check if a key exists in mapping or not in Solidity when value is of type enum?

I have the following contract in solidity.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract PocketCrypto {
enum Role{ GUARDIAN, WARD}
mapping(address => Role) public role;
function setRole(Role _role) public {
role[msg.sender] = _role;
}
}
I want to check if for a given address a Role is set or not. But since default value for mapping will be 0, and for enum it will mean first Role, how do I accomplish this?
You can extend the enum to reflect the 0th index (default) value as none.
enum Role{ NONE, GUARDIAN, WARD}

Why do constructors have to have a public and not internal visibility?

Only initializes the contract, and I don't understand why it is not an internal function. With this, is more cheap the cost of the gas insted implementing a public function
API from Solidity :
// This is the constructor which registers the
// creator and the assigned name.
constructor(bytes32 _name) public {
// State variables are accessed via their name
// and not via e.g. `this.owner`. Functions can
// be accessed directly or through `this.f`,
// but the latter provides an external view
// to the function. Especially in the constructor,
// you should not access functions externally,
// because the function does not exist yet.
// See the next section for details.
owner = msg.sender;
// We do an explicit type conversion from `address`
// to `TokenCreator` and assume that the type of
// the calling contract is `TokenCreator`, there is
// no real way to check that.
creator = TokenCreator(msg.sender);
name = _name;
}