Create a global Addressbook for deployed Smart Contracts - blockchain

I want to create a smart contract (called Deal) which, after it gets deployed, It calls another smart contract (called AddressBook) to register his address on the global AddressBook smart contract. The code I am using works, but unfortunately my newly deployed smart contract is not using the address from the AddressBook smart contract, but instead it uses his own address to call the addAddress function. The red marking shows the output if I am calling addressbook.getAddresses(addresses) inside the Deal contract. The blue marking shows the output if I am calling the getAddresses function within the AddressBook contract. So what I want is the blue output within the Deal contract
Image of the Output
Can anybody tell me how I can add the addesses of my deployed contract to a global AddressBook contract?
This his how my AddressBook smart contract looks like. I would like to add all deployed smart contracts at this contact.
contract AddressBook {
mapping(address => address[]) private _addresses;
mapping(address => mapping(address => string)) private _aliases;
function getAddresses() public view returns (address[]) {
return _addresses[msg.sender];
}
function addAddress(address addr, string _alias) public payable {
_addresses[msg.sender].push(addr);
_aliases[msg.sender][addr] = _alias;
}
function removeAddress(address addr) public payable {
uint length = _addresses[msg.sender].length;
for(uint i = 0; i < length; i++) {
if (addr == _addresses[msg.sender][i]) {
if (1 < _addresses[msg.sender].length && i < length-1) {
_addresses[msg.sender][i] = _addresses[msg.sender][length-1];
}
delete _addresses[msg.sender][length-1];
_addresses[msg.sender].length--;
delete _aliases[msg.sender][addr];
break;
}
}
}
function getAlias(address addr) public view returns (string) {
return _aliases[msg.sender][addr];
}
}
This is the smart contract I want to deploy and register at the global
AddressBook smart contract:
contract Deal {
AddressBook addressBook;
address public owner;
address public buyerAddr;
address private addr;
string private metaData;
uint private duration;
uint private price;
string private typeOfData;
string private gateKeeper;
event SafepaySent(address buyer, uint value, uint now);
/// The smart contract's constructor
function Deal(address _addressBook) public payable {
/// The seller is the contract's owner
owner = msg.sender;
AddressBook a = AddressBook(_addressBook);
a.addAddress(owner,"test");
}
}
function getAddresses(address _addressBook) public view returns (address[]) {
return AddressBook(_addressBook).getAddresses();
}
}
contract AddressBook {
function getAddresses() public view returns (address[]);
function addAddress(address addr, string _alias) public payable ;
function removeAddress(address addr) public payable;
function getAlias(address addr) public view returns (string);
}
Now I want to call the AddressBook.getAddresses() function within the AddressBook smart contract and I want to receive the addresses of all deployed Deal contracts. However, I am not receiving any address within the AddressBook smart contract. If I am calling the function Deal.getAddresses("address of the global Addressbook") I get the address of the newly deployed smart contract. But this is not what I want.

First if you want to use AddressBook as a global smart contract to track and load all the Deal contracts. You should already deploy the AddressBook contract and save it's address. Then you can load the AddressBook contract inside the constructor of the Deal contract and add the address of current Deal contract which is going to deploy, inside the already deployed global AddressBook contract. I did some working on the given contracts. I am using an array of addresses inside the AddressBook contract to track the address of all the Deal contracts. The following example code can give you good idea.
//Address Book Contract
pragma solidity ^0.5.1;
contract AddressBook {
//mapping(address => address[]) private _addresses;
address[] private _addresses;
mapping(address => mapping(address => string)) private _aliases;
function getAddresses() public view returns (address [] memory) {
return _addresses;
}
function addAddress(address addr, string memory _alias) public payable {
_addresses.push(addr);
_aliases[msg.sender][addr] = _alias;
}
}
I just focused on _address here. Following is the deal contract:
pragma solidity ^0.5.1;
import "./AddressBook.sol";
contract Deal {
AddressBook addressBook;
address public owner;
address public buyerAddr;
address private addr;
string private metaData;
uint private duration;
uint private price;
string private typeOfData;
string private gateKeeper;
event SafepaySent(address buyer, uint value, uint now);
/// The smart contract's constructor
constructor(address _addressBook) public payable {
/// The seller is the contract's owner
owner = msg.sender;
addressBook = AddressBook(_addressBook);
addressBook.addAddress(address(this),"test");
}
function getAddresses() public view returns (address[] memory) {
return addressBook.getAddresses();
}
}
You can also test and run this in remix. Hope it works.

Related

Retrieve mapping data from one contract to another contract in solidity

Here, I'm trying to get tempMap data from MainContract in Temp contract but I'm not able to get value form tempMap, as well as I'm using external visibility in MainContract but still didn’t get any response.
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract MainContract {
mapping(uint => string) public tempMap;
function addData(uint number,string memory name ) public {
tempMap[number] = name;
}
function get(uint number) external view returns(string memory){
return tempMap[number];
}
}
contract Temp{
MainContract main = new MainContract();
function getData(uint number) public view returns(string memory){
return main.get(number);
}
}
You have to pass the address of the deployed contract, so it knows where to make the call.
Your temp contract will look something like this.
contract Temp{
MainContract main;
constructor(MainContract _main) {
main = _main;
}
function getData(uint number) public view returns(string memory){
return main.get(number);
}
}

what type of variable should i use to store contracts in soldity

so, First, I imported the simpleStorage contract and then wrote this function createNeewContracts() to push the contract address into an array
everything was going smooth and I got an idea
"why not just use a struct of two variables 1. string (name of the contract owner) and 2. address (of the contract the owner owns) and i can then have name of owner and his contract as a struct stored in an array named contractAndThereArray"
I could have used mapping but I used struct and array to do the work
I ran into a problem it say
"TypeError: Invalid type for argument in function call. Invalid implicit conversion from contract SimpleStorage1 to address requested."
here is the code:-
contract StorageFactory{
// SimpleStorage public simpleStorage;
struct ownerAndThereContracts {
string name;
address nf;
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
// mapping(string => address) y;
uint256 counter;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
// address j = simpleStorage;
}
function refering(string memory _name) public {
counter++;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
saveYourContracts.push(ownerAndThereContracts(_name,simpleStorage2)); // the error occurs here it says simpleStorage2 is not address but contract
}
}
The problem is with the function referring where i tried to refer the address of a contract with the owners name but seems there is a problem
Please,if someone can explain it. Please explain I need your help guys
i've been tried to solve it for hours now but nothing seems to fit
I tried to get into your logic and fixed your contract and solve your mistake. Specifically, your error states that you cannot insert an instance of a contract into a field with datatype address. In order to solve this problem you need to cast the contract instance in address datatype. You can see the contract in the following lines, I have also inserted some notes to let you understand what I have changed:
// SDPX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./SimpleStorage1.sol";
contract StorageFactory{
uint256 counter;
struct ownerAndThereContracts{
string name;
address nf; // NOTE: I assume that it's the SimpleStorage address
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
}
function refering(string memory _name) public {
// NOTE: I assume that when creating new contract, then you must refering it directly to an owner.
// In this case, I retrieve the length of array in details the last element index.
counter = x.length-1;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
// NOTE: You must cast your contract instance to an address for put it into your struct (because the datatype is 'address')
saveYourContracts.push(ownerAndThereContracts(_name,address(simpleStorage2)));
}
}
Ok first i fixed your code, you are missing 2 casting, first to address and then to a paybale address.
Here:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;
contract SimpleStorage1{
}
contract StorageFactory{
// SimpleStorage public simpleStorage;
struct ownerAndThereContracts {
string name;
address nf;
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
// mapping(string => address) y;
uint256 counter;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
// address j = simpleStorage;
}
function refering(string memory _name) public {
counter++;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
address simpleStorage2Address = address(simpleStorage2); //first cast to address
address payable _finalCast = payable(simpleStorage2Address); // then cast to payable address
saveYourContracts.push(ownerAndThereContracts(_name, _finalCast));
}
But you should know that this is a very costy contract, you should take out all the process of saving the contract to a environment like c or java and only create the contract through solidity so the objects on memory wont cost you.
Anyway good luck!
From docs: contract-types
Explicit conversion to and from the address payable type is only
possible if the contract type has a receive or payable fallback
function. The conversion is still performed using address(x). If the
contract type does not have a receive or payable fallback function,
the conversion to address payable can be done using
payable(address(x))
I explained here contract-type vs address type
In Solidity a contract variable is really just an address under the
hood.

TypeError: Member "push" not found or not visible after argument-dependent lookup in address[] storage ref

could anyone help me with this??
used online remix in order to create a calucator using following criteria
Add Log of transactions using the event/emit
Each time one of the methods is called you will add
the address (msg.sender)
the action (“add”, “subtract”…)
the number
ii. Create a modifier “isOwner” like we did in class and add it to all the
methods in the calculator.
iii. Add a check using require or revert for the divide method to make sure
you are not dividing by zero (0).
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract Calculator{
mapping(address => uint256) public transactions;
address public owner;
address[] public transList; //// Showing to modify this line of code
constructor() {
owner = msg.sender;
}
modifier isOwner() {
require(msg.sender == owner, "Sender is not Owner");
_;
}
function whoIsOwner() public isOwner view returns (address) {
return owner;
}
uint256 public total =0;
uint256 public current_total =0;
function add(uint256 _amount) isOwner public{
total = total + _amount;
transList.push(msg.sender);
transList.push("add"); /// Error in this line
transList.push(_amount);
}

solidity: how can i call a payable function from another contract and enter the amount i want to pay? the other contract is not on the editor

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface IBank {
function addTax(uint256 moneyToAdd) external payable;
}
contract Counter {
uint public count;
address bankAddress;
function setbankAddress(address _bankAddress) public payable {
bankAddress = _bankAddress;
}
function addMon(uint moneyToAdd) public payable {
require(moneyToAdd <= msg.value, "Ether value sent is not
correct");
}
function pay(uint _Amount) public payable {
IBank(bankAddress).addTax{value:_Amount}(_Amount);
}
}
when I deploy it I first add the contract address that I want to interact with, it's working with all functions that do not require value

How to Call contract inside another contarct in solidity version 0.5.2?

I'm using solidity version 0.5.2
pragma solidity ^0.5.2;
contract CampaignFactory{
address[] public deployedCampaigns;
function createCampaign(uint minimum) public{
address newCampaign = new Campaign(minimum,msg.sender); //Error
//here!!!
deployedCampaigns.push(newCampaign);
}
function getDeployedCampaigns() public view returns(address[] memory){
return deployedCampaigns;
}
}
I'm getting the error while assigning calling the Campaign contract inside CampaignFactory contract
TypeError: Type contract Campaign is not implicitly convertible to expected
type address.
address newCampaign = new Campaign(minimum,msg.sender);
I have another contract called Campaign which i want to access inside CampaignFactory.
contract Campaign{
//some variable declarations and some codes here......
and I have the constructor as below
constructor (uint minimum,address creator) public{
manager=creator;
minimumContribution=minimum;
}
You can just cast it:
address newCampaign = address(new Campaign(minimum,msg.sender));
Or better yet, stop using address and use the more specific type Campaign:
pragma solidity ^0.5.2;
contract CampaignFactory{
Campaign[] public deployedCampaigns;
function createCampaign(uint minimum) public {
Campaign newCampaign = new Campaign(minimum, msg.sender);
deployedCampaigns.push(newCampaign);
}
function getDeployedCampaigns() public view returns(Campaign[] memory) {
return deployedCampaigns;
}
}
To call an existing contract from another contract ,pass the contract address inside cast
pragma solidity ^0.5.1;
contract D {
uint x;
constructor (uint a) public {
x = a;
}
function getX() public view returns(uint a)
{
return x;
}
}
contract C {
//DAddress : is the exsiting contract instance address after deployment
function getValue(address DAddress) public view returns(uint a){
D d =D(DAddress);
a=d.getX();
}
}