Can't use array of contracts inside a function in solidity - solidity

Can someone please explain me why this works fine
import "./SimpleStorage.sol";
pragma solidity ^0.6.0;
contract storageFactoryContract {
SimpleStorage[] public asd;
function createSimpleStorageContract() public{
SimpleStorage simpleStorage = new SimpleStorage();
}
}
but this doesn't
import "./SimpleStorage.sol";
pragma solidity ^0.6.0;
contract storageFactoryContract {
function createSimpleStorageContract() public{
SimpleStorage[] public asd;
SimpleStorage simpleStorage = new SimpleStorage();
}
}
The error is:
freecodecamptutorial/FactoryContract.sol:14:26: ParserError: Expected ';' but got 'public'
SimpleStorage[] public asd;
^----^

In the second snippet, you're trying to set a visibility modifier for a regular variable. Only state variables (i.e. contract properties) and functions can have visibility modifiers.
Reference type variables (such as a contract) need to also have a data location. Since you're not working with the variable further, you can safely use the memory location. If you were to store it in storage, you might want to use the storage data location.
function createSimpleStorageContract() public {
// removed the `public` modifier
// added the `memory` data location
SimpleStorage[] memory asd;
SimpleStorage simpleStorage = new SimpleStorage();
}
This will generate two warnings about the unused variables asd and simpleStorage. It's simply because you're assigning the variables but never using them later. In this context, you can safely ignore them.
Note: I'm assuming that the SimpleStorage is a contract without a constructor or with a 0-argument constructor. Otherwise, you might get some different errors, for example wrong argument count.

Related

i am unable to use _totalSupply and _balances any private data type in OpenZeppelin and shows Undeclared identifier in solidity

Hey i am unable to implement _totalSupply and _balances in Remix but able to use remaining functions like name() and decimal() and symbol()
this is my code
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract METoken is ERC20 {
constructor(uint256 initialSupply) ERC20 ("MAstering ther","MET")
{
_totalSupply=initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
}
i am using ERC20 and i have seen from ERC20.sol file from Github that there are _totalSupply and other variables to use the totalSupply() method but i am not able to use them plz help!
In the OpenZeppelin ERC20 implementation, that you're importing to your contract, properties _totalSupply and _balances have the private visibility.
From the Solidity docs page:
Private state variables are like internal ones but they are not visible in derived contracts.
So these specific properties (with private visibility) are not visible in your contract that derives from the contract that declares them.
Solution: The parent contract defines the _mint() function that effectively increases the balance of a selected address, the total supply, as well as emits the Transfer event.
constructor(uint256 initialSupply) ERC20 ("MAstering ther","MET")
{
// increases `msg.sender`'s balance, total supply, and emits the `Transfer` event
_mint(msg.sender, initialSupply);
}

Read contract variable with only interface definition

I'm playing ethernaut Level 3, the original contract is here: https://ethernaut.openzeppelin.com/level/0x4dF32584890A0026e56f7535d0f2C6486753624f
When consecutiveWins is bigger or equal to 10, the player wins:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import '#openzeppelin/contracts/math/SafeMath.sol';
contract CoinFlip {
using SafeMath for uint256;
uint256 public consecutiveWins;
...
}
Now I want to read the consecutiveWins value in my contract, so I defined an interface:
interface CoinFlip {
uint256 public consecutiveWins;
function flip(bool _guess) external returns (bool);
}
But it is not allowed to have a variable in an interface, what should I do?
Solidity compiler will automatically generate getter functions for public variables, so what you need is replacing consecutiveWins variable in your interface with a getter function like this:
function consecutiveWins() public view returns (uint256);
You can read more about it in Solidity docs here.

Send array of structs to a different contract

It is mentioned here that ABIEncoderV2 should make it possible to pass structs from contract to contract. Solidity latest ABI spec mentions that it is possible to have tuple array as a input. Can you please say how array of structs / tuple[] should be sent in below example code from TupleArrayFactory to TupleArray?
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract TupleArrayFactory {
TupleArray newTuple;
function createTuple() public {
newTuple = new TupleArray("trait0", "display0", 0);
// newTuple.pushAttribute([["trait1","display2",2]]);
newTuple.pushAttribute(["trait1","display2",2]);
// TypeError: Unable to deduce common type for array elements.
}
}
contract TupleArray {
struct Attribute {
string trait_type;
string display_type;
uint8 value;
}
Attribute[] public attributes;
Attribute[] public tempAttributeArr;
constructor(string memory trait_type, string memory display_type, uint8 value) payable {
Attribute memory Attribute0 = Attribute(trait_type, display_type, value);
tempAttributeArr.push(Attribute0);
pushAttribute(tempAttributeArr);
//pushAttribute([trait_type, display_type, value]);
// TypeError: Unable to deduce common type for array elements.
}
function pushAttribute(Attribute[] memory _attr) public payable {
attributes.push(_attr[0]);
}
}
Here's a working version of your example:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract TupleArrayFactory {
TupleArray newTuple;
function createTuple() public {
newTuple = new TupleArray("trait0", "display0", 0);
TupleArray.Attribute[] memory attributes = new TupleArray.Attribute[](1);
attributes[0] = TupleArray.Attribute("trait1", "display2", 2);
newTuple.pushAttribute(attributes);
}
}
contract TupleArray {
struct Attribute {
string trait_type;
string display_type;
uint8 value;
}
Attribute[] public attributes;
constructor(string memory trait_type, string memory display_type, uint8 value) payable {
Attribute[] memory tempAttributeArr = new Attribute[](1);
tempAttributeArr[0] = Attribute(trait_type, display_type, value);
pushAttribute(tempAttributeArr);
}
function pushAttribute(Attribute[] memory _attr) public payable {
attributes.push(_attr[0]);
}
}
Some remarks:
pushAttribute([["trait1","display2",2]]) won't work because an array is not implicitly convertible to a struct. You have to invoke the struct constructor.
Even then pushAttribute([TupleArray.Attribute("trait1","display2",2)]) won't work because Solidity currently does not have dynamic array literals. If you want to pass a dynamic array into a function you have to create a variable for it.
Your pushAttribute() takes an array but ignores all but the first element. So why make it an array at all? I'm assuming it's for the sake of the example but if not, you should make the function just accept a single struct.
Putting tempAttributeArr in storage works but is not necessary. You can put it in memory, which is cheaper.
Solidity latest ABI spec mentions that it is possible to have tuple array as a input.
The docs you are linking to only describe how tuples (used for example to return named function arguments or return values) are formatted in the JSON describing the ABI.
Maybe you're referring to some other section on that page? In general, structs are encoded as tuples the ABI, which might be the source of confusion there. But this simply means that if you are encoding the parameters yourself (e.g. when you use off-chain code to issue a transaction), you should encode structs as tuples. If you are just calling external functions on chain, you do not have to do that. In fact you can't because structs and tuples are not convertible to each other. You have to use an actual struct when a function expects a struct and the struct type must be the exact one specified in function signature.

Erorr after truffle compile in Erc721 openzeppelin contract

im doing step by step of this article and i had a problem on truffle compile part.
I've got this error in cmd:
Error parsing #openzeppelin/contracts/token/ERC721/ERC721.sol: ParsedContract.sol:51:72: ParserError: Expected '{' but got reserved keyword 'override'
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
^------^
my contract :
pragma solidity ^0.6.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract Uniken is ERC721{
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
mapping(string => uint8) hashes;
constructor() public ERC721("Uniken", "Ukn") {
}
function awardItem(address recipient, string memory hash, string memory metadata)
public
returns (uint256)
{
require(hashes[hash] != 1);
hashes[hash] = 1;
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, metadata);
return newItemId;
}
}
I'd be thankfull if anyone tell me whatis the problem?
It seems like it isn't seeing the ERC165 contract that ERC721 extends from. That function that it is getting stuck on should be overriding a function of the same name in ERC165, but the truffle compiler doesn't see a function named supportsInterface() in a class that ERC721 inherits from. So I would check to make sure everything imported in the ERC721 smart contract is in the right place in your folder structures, and that ERC721 is correctly inheriting ERC165.
After made some research , I was in truffle version 5.0 and update to the latest version of truffle -> v5.4.6, I am now able to compile

Ways to get the value of mapping public?

I have this piece of code, but I dont have implemented a view returns function.
mapping (uint256 => TokenTimeLockInfo) public locks;
struct TokenTimeLockInfo {
Token token;
address beneficiary;
uint256 amount;
uint256 unlockTime;
}
I can access the value way web3js are possible?
Or do I need another contract to implement a view returns?
Since the property is public, you can access it using the getter function automatically generated by Solidity compiler.
const myContract = new web3.eth.Contract(abiJson, contractAddress);
// returns value of the mapping for the key `0`
const info = await myContract.methods.locks(0).call();
Docs:
https://docs.soliditylang.org/en/v0.8.6/contracts.html#getter-functions
https://web3js.readthedocs.io/en/v1.3.4/web3-eth-contract.html#methods-mymethod-call