0

I'm working on two contracts, one of which will contain an array of indeterminate size. The second contract wants to request a subset of this contract for its functions. My initial attempts seem to suggest that this is either difficult or impossible, at least without some sort of Rube-Goldberg-esque machinery. Does anyone have any suggestions? The code is here:

pragma solidity ^0.4.19;
contract EMWhiteList {
    /*This contract is meant to abstract out the whitelist functionality from the EMBallot contract so that the voting contracts can be 
    reused more easily. IE we will be able to create a new EMBallot for each county and have a seperate whiteList for each.
    */
    address[] whiteList;
    struct Voter {
        address addr;
        string region;
    }
    Voter[] voters;
    address[] regionalVoters; 

    function addToWhiteList (address voter){
        whiteList.push(voter);
    }

    function returnWhiteList () constant returns(address[]){
        return whiteList;    
    }

    function addVoter(address key, string region){
        Voter memory newVoter = Voter (key, region);
        voters.push(newVoter);
    }

    function getRegion(string region) constant returns (address[]){
        for(uint8 i=0; i<voters.length; i++){
            if(keccak256(voters[i].region) == keccak256(region)){
                regionalVoters.push(voters[i].addr);     
            }
        }    
    }

    function getVoter(uint256 key) constant returns(address){
        return voters[key].addr;    
    }
}

contract RegionalContract {
    address[] whiteList;    

    function getList(string region, address whiteListAddress){
        EMWhiteList fullWL = EMWhiteList(whiteListAddress);
        whiteList = fullWL.getRegion(region);
    }

}
1

You need to organize the data so that any needed operation can be completed in a single operation without iteration. Basically, for loops are dangerous.

This WL sketch (no warranty) shows how the lookups and signals are easy to fetch with a supporting data structure.

It's passing boolean replies and avoiding passing large objects.

pragma solidity ^0.4.20;

contract WL {

    struct VoterStruct {
        // attributes that are not keys
        bool isVoter; // soft delete
    }

    struct RegionStruct {
        // attributes that are not keys
        mapping(address => bool) isVoter;
        address[] voterList; // one region to many voters
        bool isRegion; // soft delete
    }

    // append-only style

    mapping(address => VoterStruct) public voterStructs;
    address[] public voterList;

    mapping(bytes32 => RegionStruct) public regionStructs;
    bytes32[] public regionList;

    function isVoter(address voter) public view returns(bool) {
        return voterStructs[voter].isVoter;
    }

    function isRegion(bytes32 region) public view returns(bool) {
        return regionStructs[region].isRegion;
    }

    function isRegionVoter(bytes32 region, address voter) public view returns(bool) {
        return regionStructs[region].isVoter[voter];
    }

    function getRegionVoterAtRow(bytes32 region, uint row) public view returns(address) {
        return regionStructs[region].voterList[row];
    }

    function getVoterCount() public view returns(uint) {
        return voterList.length;
    }

    function getRegionCount() public view returns(uint) {
        return regionList.length;
    }

    function getRegionVoterCount(bytes32 region) public view returns(uint) {
        return regionStructs[region].voterList.length;
    }

    // setters

    function appendRegion(bytes32 region) public {
        require(!isRegion(region));
        regionStructs[region].isRegion = true;
        regionList.push(region);
    }

    function appendVoter(address voter) public {
        require(!isVoter(voter));
        voterStructs[voter].isVoter = true;
        voterList.push(voter);
    }

    function registerVoterInRegion(bytes32 region, address voter) public {
        require(isVoter(voter));
        require(isRegion(region));
        require(!isRegionVoter(region,voter));
        regionStructs[region].voterList.push(voter);
        regionStructs[region].isVoter[voter] = true;
    }

    // add soft delete functions that set bools to false
}

Some more ideas over here. Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

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.