Declaration Error: Undeclared identifier Solidity - solidity

I am new to Solidity. I am using an interface and a library for an exercise in Solidity. The contract must implement the methods from the interface, with the help of the functions from the library. I get a Declaration Error: Undeclared identifier for mapPerson and mapCompany. Where do I go wrong? I have tried to put the structs in the library, but then I get other errors, because of the logic I have implemented. Here is my code:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
struct Person{
address addr;
string name;
string surname;
}
struct Company{
address addr;
string name;
}
interface Interface{
function addPerson(address addr, string memory name, string memory surname) external;
function addCompany(address addr, string memory name) external;
function getPerson() external view returns (address addr);
function getCompany() external view returns (address addr);
}
library Lib{
function addPerson(address addr, string memory name, string memory surname) public{
addr = msg.sender;
mapPerson[addr] = Person(name, surname, addr);
}
function addCompany(address addr, string memory name) public{
addr = msg.sender;
mapCompany[addr] = Company(addr, name);
}
}
contract Lab03 is Interface{
Person p;
Company c;
mapping(address => Person) mapPerson;
mapping(address => Company) mapCompany;
function addPerson(address addr, string memory name, string memory surname) public override {
Lib.addPerson(addr, name, surname);
emit addPersonEvent(addr, name, surname);
}
function addCompany(address addr, string memory name) public override{
Lib.addCompany(addr, name);
emit addCompanyEvent(addr, name);
}
function getPerson() public override view returns (address addr) {
return p.addr;
}
function getCompany() public override view returns (address addr) {
return c.addr;
}
event addPersonEvent(address addr, string name, string surname);
event addCompanyEvent(address addr, string name);
}

In your smart contract code you must to define the mappings inside the 'contract' keyword. In your case remove the mapPerson and map Company from the struct mappings and put them after the keyword 'contract' in this way:
contract Lab03 is Interface{
// Add here the mappings and remove them from the struct
mapping(address => Person) mapPerson;
mapping(address => Company) mapCompany;
Person p;
Company c;
...
UPDATED ANSWER
For use a mapping into a library, you must to use a struct in which we can declare the mapping. At this point in your smart contract, you must define the instance of structs created in the library and this state variables must to be passed when you want to read/insert/update items in the mapping. Said that, try this:
Said that, try this solution:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
struct Person{
address addr;
string name;
string surname;
}
struct Company{
address addr;
string name;
}
interface Interface{
function addPerson(address addr, string memory name, string memory surname) external;
function addCompany(address addr, string memory name) external;
function getPerson(address addrFind) external view returns (address addr);
function getCompany(address addrFind) external view returns (address addr);
}
library Lib{
// define struct with mapping
struct LibPerson {
mapping(address => Person) mapPerson;
}
struct LibCompany {
mapping(address => Company) mapCompany;
}
function addPerson(LibPerson storage lp, address addr, string memory name, string memory surname) public{
addr = msg.sender;
lp.mapPerson[addr] = Person(addr, name, surname);
}
function addCompany(LibCompany storage lc, address addr, string memory name) public{
addr = msg.sender;
lc.mapCompany[addr] = Company(addr, name);
}
function getCompany(LibCompany storage lc, address addrFind) view external returns(address){
return lc.mapCompany[addrFind].addr;
}
function getPerson(LibPerson storage lp, address addrFind) view external returns(address){
return lp.mapPerson[addrFind].addr;
}
}
contract Lab03 is Interface{
// define state variable for two struct present in the library
Lib.LibPerson libP;
Lib.LibCompany libC;
Person p;
Company c;
function addPerson(address addr, string memory name, string memory surname) public override {
Lib.addPerson(libP, addr, name, surname);
emit addPersonEvent(addr, name, surname);
}
function addCompany(address addr, string memory name) public override{
Lib.addCompany(libC, addr, name);
emit addCompanyEvent(addr, name);
}
function getPerson(address _addressFind) public override view returns (address addr) {
return Lib.getPerson(libP, _addressFind);
}
function getCompany(address _addressFind) public override view returns (address addr) {
return Lib.getCompany(libC, _addressFind);
}
event addPersonEvent(address addr, string name, string surname);
event addCompanyEvent(address addr, string name);
}

These lines should be outside of the structs (Person, Company):
mapping(address => Person) mapPerson;
mapping(address => Company) mapCompany;
like :
struct Person{
address addr;
string name;
string surname;
}
mapping(address => Person) mapPerson;

Related

How to pass a function as an parameter to a contract in solidity

I'm trying to make a dynamic rule builder in solidity, I have a role manager contract that looks like so:
import "#openzeppelin/contracts/access/Ownable.sol";
// The Ownable contract to manage the contract owner
contract RoleManager is Ownable {
mapping(bytes32 => function(bytes32, address, address[] memory, uint256[] memory, bytes[] memory, string memory) external view returns (bool)) public rules;
// Set the rule for the given role
function setRule(bytes32 role, function(bytes32, address, address[] memory, uint256[] memory, bytes[] memory, string memory) external view returns (bool) rule) public onlyOwner {
rules[role] = rule;
}
//...
}
Maybe my understanding of what function parameter is wrong, I would like to build a dynamic function, How to I generate a function on ethers to pass to this ?
Use interface :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/access/Ownable.sol";
interface IRule {
function rule (bytes32 data, address addr,
address[] memory addrArr, uint256[] memory uintArr,
bytes[] memory dataArr, string memory str)
external view returns (bool);
}
contract Demo is Ownable {
mapping(bytes32 => IRule) public rules;
function setRule(bytes32 role, IRule rule) public onlyOwner {
rules[role] = rule;
}
}

When (and when not) to use the new keyword in Solidity

I have two contracts in Solidity like so (based upon a tutorial):
pragma solidity >=0.4.16 <0.9.0;
contract ERC20Token {
string public name;
mapping(address => uint) public balances;
function mint() public {
balances[tx.origin]++;
}
}
contract MyContract {
address payable wallet;
address public token;
constructor(address payable _wallet, address _token) {
wallet = _wallet;
token = _token;
}
function buyToken() public payable {
ERC20Token _token = ERC20Token(address(token));
_token.mint();
wallet.transfer(msg.value);
}
}
My question is why they use ERC20Token _token = ERC20Token(address(token)); in order to access the class and call he .mint() function.
My base reflex would be to do the following instead:
ERC20Token _token = new ERC20Token();
_token.mint();
This is because the ERC20Token contract does not have a constructor, so I'm unsure where the RC20Token(address(token)) constructor parameters come from.
The new ERC20Token() expression deploys a new ERC20Token contract and returns its (newly deployed) address.
Since your ERC20Token doesn't have any constructor (and constructor params), you don't need to pass any params. But if it did have constructor params, you'd need to pass them. Example:
contract ERC20Token {
constructor (string memory _name, string memory _symbol) {
}
}
address deployedTo = new ERC20Token("MyToken", "MyT");
The ERC20Token _token = ERC20Token(<address>) creates a helper object allowing the _token to be treated as a contract implementing the ERC20Token interface, so you can execute and call its public and external functions.
It's the address of the external contract that you're passing - not the constructor params.
contract ERC20Token {
function mint() public {
}
}
ERC20Token _token = ERC20Token(address(token));
_token.mint();

The constructor should be payable if you send value

I'm running this code on remix IDE. Everything is working fine except the function transfertocontracts(uint amount) public. I'm trying to transfer some ethers for e.g. 10 to my contract and then later using this function function Transfer_Contract_Amount() public I will transfer all the amount of contract to specific address.
The problem is that when I run function transfertocontracts(uint amount) public I'm getting this Error:
Note: The constructor should be payable if you send value. debug the transaction to get more information.
contract SLA {
address seller;
event DepositFunds(address from, uint amount);
constructor() payable public {
seller = msg.sender;
}
function transfertocontracts(uint amount) public {
address(this).transfer(amount);
}
function seePerson_Amount() public view returns(uint) {
return seller.balance;
}
function seeContract_Amount() public view returns(uint) {
return address(this).balance;
}
function Transfer_Contract_Amount() public {
seller.transfer(address(this).balance);
}
}
You can send ether only by using the value attribute which you can set while interacting with the Smart Contract. Below is the working code
pragma solidity >=0.4.22 <0.6.0;
contract SLA{
address payable seller;
event DepositFunds(address from, uint amount);
constructor() payable public {
seller = msg.sender;
}
function transfertocontracts(uint amount) payable public{
}
function seePerson_Amount() public view returns(uint){
return seller.balance;
}
function seeContract_Amount() public view returns(uint){
return address(this).balance;
}
function Transfer_Contract_Amount() payable public{
seller.transfer(address(this).balance);
}
}
To check you can run it on remix and on the run tab on the left side you can putt the value of ether to send and run the transfertocontracts function further to store the value its a good idea to use the msg.value.

Truffle compile

I get this Truffle error when I compile. I have tried adding payable to the addresses but it won't work. This is the error:
TypeError: Member "transfer" not found or not visible after argument-dependent lookup in address. buyer.transfer(Orders[order_no].price*8/10); ^------------^
pragma solidity >0.4.99 <0.6.0;
contract ManageOrder{
address public owner;
uint256 count;
uint256 count_parking;
string order_list;
uint256 order_number;
string public result;
//order table
struct Order {
uint256 orderNo;
address buyer;
address seller;
uint256 parkingNo;
State state;
string new_hour;
uint256 price;
uint date;
}
//parking table
struct Parking {
uint256 parkingNo;
address seller;
string name;
string phone;
string post_code;
string avail_hour;
string park_address;
}
//buyer table
struct Buyer {
string name;
string phone;
}
//map the struct to an index
mapping(uint => Order) private Orders;
mapping(uint => Parking) private Parkings;
mapping(address => uint256) balances;
mapping(address => Buyer) public Buyers;
//for sellers and buyers to abort the order
//order state should be pending
function abortOrder(uint256 order_no) public
inState(State.Pending,order_no)
{
//get the address of both the buyer and the seller
address buyer = Orders[order_no].buyer;
address seller = Orders[order_no].seller;
//if the message sender id the buyer
if(msg.sender==Orders[order_no].buyer)
{
Orders[order_no].state = State.Aborted;
//return 80% of the money to buyer
buyer.transfer(Orders[order_no].price*8/10);
//20% of the money to the seller
seller.transfer(Orders[order_no].price*2/10);
}
else if(msg.sender==Orders[order_no].seller)
{
//if the sender is the seller, he needs to pay 20% of the parking fee to the buyer
Orders[order_no].state = State.Aborted;
//return the money to buyer
buyer.transfer(Orders[order_no].price*12/10);
balances[seller]-=Orders[order_no].price*2/10;
}
}
Check the breaking changes in Solidiy 0.5.x.
The address type was split into address and address payable, where only address payable provides the transfer function
https://solidity.readthedocs.io/en/v0.5.3/050-breaking-changes.html?highlight=address%20payable

In Remix - Solidity IDE, How to pass arguments?

I'm studying smart contracts on solidity and I ran into a problem. Every time I try to create this contract, my arguments are not confirmed.
I expected a "OreOreCoin" to come out when I chose name, but instead I get an empty string.
and
This my code:
pragma solidity ^0.4.8;
contract OreOreCoin{
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping (address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
function OreOreCoin(uint256 _supply, string _name, string _symbol, uint8
_demicals){
balanceOf[msg.sender] = _supply;
name = _name;
symbol = _symbol;
decimals = _demicals;
totalSupply = _supply;
}
function transfer(address _to, uint256 _value){
if(balanceOf[msg.sender] < _value) throw;
if(balanceOf[_to] + _value < balanceOf[_to]) throw;
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
Transfer(msg.sender,_to,_value);
}
}
What could be the problem?
Don’t quote the entire parameter list. In doing so, you're sending a single string parameter into the constructor that is converted to a uint256 for _supply and the rest are defaulted. You can confirm this by looking at the details of the transaction in the Remix UI.
The parameter list should just be:
10000,”OreOreCoin”,”oc”,0