I am currently working on voting contracts modeled after a particular electoral system.
My intention is to first deploy the MasterConstituency contract manually and to have that contract deploy multiple instances of the BaseConstituency contract. Eventually, I will transfer ownership of BaseConstituencies to separate addresses that will be operated independently.
I have two contracts; namely
MasterConstituency.sol
pragma solidity ^0.4.24;
import "./Ownable.sol";
import "./BaseConstituency.sol";
contract MasterConstituency is Ownable {
enum ConstituencyType {FEDERAL, STATE}
uint totalVotes;
modifier isValidConstituencyType(uint _constituencyType){
require(uint(ConstituencyType.STATE) >= _constituencyType);
_;
}
modifier isUniqueParty(string _name){
for (uint x = 0; x < parties.length; x++) {
if (compareStrings(parties[x].name, _name)) {
revert();
}
}
_;
}
struct Party {
string name;
string abbreviation;
}
struct Candidate {
string name;
uint numVotes;
bool validCandidate;
}
struct Voter {
bool hasVoted;
bool validFederalVote;
bool validStateVote;
uint federalCandidateVote;
uint stateCandidateVote;
}
Candidate[] candidates;
Party[] parties;
mapping(string => Voter) votes;
mapping(string => address) constituencies;
mapping(uint => uint) candidateToParty;
function initialiseConstituency(
uint _constituencyType,
string _constituencyCode,
string _constituencyName) public onlyOwner() isValidConstituencyType(_constituencyType) returns (address) {
address constituency = new BaseConstituency(_constituencyType, _constituencyName);
constituencies[_constituencyCode] = constituency;
return constituency;
}
function registerParty(string _name, string _abbreviation) public onlyOwner() isUniqueParty(_name) {
parties.push(Party(_name, _abbreviation));
}
function getConstituencyAddress(string _constituencyCode) public view returns (address) {
return constituencies[_constituencyCode];
}
function compareStrings(string a, string b) public pure returns (bool){
bytes32 c = keccak256(abi.encodePacked(a));
bytes32 d = keccak256(abi.encodePacked(b));
return c == d;
}
}
BaseConstituency.sol
pragma solidity ^0.4.24;
import "./Ownable.sol";
contract BaseConstituency is Ownable {
uint numVotes;
uint constituencyType;
string constituencyName;
struct Candidate {
string name;
uint numVotes;
bool validCandidate;
}
struct Voter {
bool hasVoted;
bool validVote;
uint candidateVote;
}
Candidate[] candidates;
constructor(uint _constituencyType, string _constituencyName) public{
numVotes = 0;
constituencyType = _constituencyType;
constituencyName = _constituencyName;
}
function getStuff() public view returns(uint, string){
return (constituencyType, constituencyName);
}
}
The Ownable contract I'm using: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ownership/Ownable.sol
It is still a work in progress and I have not implemented all the functions necessary for a proper smart contract. I'm currently developing and testing the smart contract on the Remix IDE and Ganache (with MetaMask of course), but the issue I'm facing is emulated on the Rinkeby testnet.
Currently, I'm attempting to interact with the BaseConstituency contract deployed through Remix. The issue I'm facing arises when I call initialiseConstituency
and subsequently obtain the address of the deployed BaseConstituency contract.
I load the retrieved BaseConstituency contract address in Remix, but this is what is shown instead:
Through Remix, it appears the address does not point to the expected BaseConstituency contract, but the MasterConstituency contract instead.
I was expecting to see something like this on Rinkeby Etherscan:
But instead, I see this:
I also realised that the owner of the deployed BaseConstituency contract is the address of the MasterConstituency contract, but that can be rectified by transferring ownership to the owner of MasterConstituency.
I would like to know why this is so. Do I have to communicate through MasterConstituency to get to BaseConstituency? It is probable that my understanding of contract-to-contract deployment is erroneous, hence any recommendation or advice to my current design is appreciated.
P.S. I apologise for the very long post, but I believe a detailed description of the issue is the best way to go.