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

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

Related

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}

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

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.

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;
}

Should the implementation of value object be sealed?

Following DDD practices, should the implementation of value object be sealed?
Imagine having some abstract ValueObject<T> and the concrete implementation given as Money : ValueObject<Money>. Should I seal Money?
public class Money : ValueObject<Money>
{
private Money()
{
}
private Money(decimal value, string currency)
{
Requires.NotEmpty(currency, nameof(currency));
Requires.That(value >= 0, $"{nameof(value)} must be greater or equals to 0.");
Value = value;
Currency = currency.ToUpper();
}
public decimal Value { get; private set; }
/// <summary>
/// ISO 4217 currency code
/// </summary>
public string Currency { get; private set; }
public static Money Dkk(decimal value) => new Money(value, "DKK");
public static Money Usd(decimal value) => new Money(value, "USD");
}
Generally it's best practices to avoid polymorphism due to the composition over inheritance advice. In the DDD context there are some cases where it's useful to allow future polymorphism but this usually includes entities.
Value object per definition should be immutable and to avoid further misuse, seal it.
Useful link: http://thepaulrayner.com/value-objects-and-immutability/
To me, Value Object vs other type of object makes little difference when considering sealing. Countless arguments have been made both for and against it over the years with complex enough considerations that you don't want to add another variable to the equation.
I can hardly see all VO's in a domain model being sealed but all other classes not sealed. If you're going to seal, it will primarily be for a whole different range of reasons (organizational, performance) that don't have much to do with the type of object in the DDD nomenclature.