3

I am currently developing a dApp with Drizzle on top of ReactJS.

My project consists of, basically, 8 .sol files. 4 of them are just abstract contracts that include the functions, structs etc. for easier human readability and the other 4 hold the logic of the contracts.

My main issue is that some of the contracts must be unique to every user - The user should be able to create a new instance of a contract for as many times as they want.

I have tried to do it by having one more contract that will create the new instances, like this:

pragma solidity ^0.5.10;

import './ContractToBeInstanced.sol';
contract newInstance {
  function newInstanceFunc(address _address) public returns(address) {
    ContractToBeInstanced T = new ContractToBeInstanced(_address);
    return T.getAddress(); //returns the address(this) of the contract
  }
}

and in the ContractToBeInstanced.sol I have a constructor that it sets the owner of the new instance:

  constructor(address _owner) public {
    owner = _owner;
    getAddress(); //it also calls the getAddress() to return the address to the parent function
  }

So, my main issues are:

  • How do I create that instance through Drizzle? For example, I have tried:
<Button onClick={ () => this.contracts.newInstance.methods.newInstanceFunc.cacheSend(contractConfig.contractName, {from: this.currentAccount})) }>New Instance</Button>

Metamask opens, I run the transaction, it gets valid and then, nothing. I also can not see the new (instance) of the contract in the Contracts menu in Ganache and there is no output in the transactions that returns the new contract's address. Is all this normal?

  • When the new instance of the contract will be created, how will I be able to access it again in a later manner of time? I suspect that I will have to use some kind of IPFS or look through the past transactions? I know that this is a very simple question, but I am not really sure yet.

What I would also like to note, is that my truffle's migration files only do a:

deployer.deploy(ContractA).then( () => deployer.deploy(ContractB)...);

which I think is wrong and that the Migrations.sol is untouched.

0

In your factory contract, you can track the instances created.

pragma solidity ^0.5.10;

import './ContractToBeInstanced.sol';
contract newInstance {

 mapping(address=>address) public userContracts;

  function newInstanceFunc(address _address) public returns(address) {
    ContractToBeInstanced T = new ContractToBeInstanced(_address);
    address deployedAddress = address(T);
    userContracts[_address] = deployedAddress;
    return deployedAddress;
  }
}

Edit: I have made an edit that could do away with the getAddress function in the ContractToBeInstantiated.

  • Thank you Sanjay. – GeorgePal Sep 5 at 0:53
0

For anyone that may have the same problem, I followed Sanjay's answer and made some adjustments to it so it can fit my case better.

For the reason that I want users to have as many identities as they want (and name them), I needed a struct. So, I did this:

Created a struct which holds the:

  • Address of the user
  • Address of the instance
  • The name that the user gave to the contract

Then, I created a mapping to correlate all this. You can see the rest by reading the code below.

contract newInstance {

  struct someNewInstance {
    address usersAddress;
    address instanceAddress;
    string nameForTheInstance;
    bool instanceExists
  }

  mapping(address => mapping(bytes32 => someInstance)) public contractInstances;
  someInstance[] public listOfContracts;
  uint public instancesLength; //I use this to receive the number of the instances. Thus, I can loop and receive all the instances very easy!


  function createNewInstance(string memory _name) public returns(address) {
    bytes32 _id = keccak256(abi.encodePacked(msg.sender, _name));

    require(contractInstances[msg.sender][_id].instanceExists == false, "There is already an Identity with this name"); //Just checks

    theContractToBeInstanced newInstance = new theContractToBeInstanced(msg.sender);
    address instanceAddress = address(newInstance);

    someInstance memory newInstanceStruct = someInstance(msg.sender, deployedAddress, _name, true);
    listOfContracts.push(newInstanceStruct);

    contractInstances[msg.sender][_id] = newInstanceStruct;
    instancesLength++;

    return deployedAddress;
  }

}

It is possible that the code above needs some readjustment to be more efficient, but for now and for the testing that I am doing, it works.

Cheers =)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.