0

I as trying to add methods in a contract, but it got so big that i couldn't deploy it with truffle. Now i need to create an otehr contract that will be called instead of the original contract to process data stored in the original contract as state variable.

The variable i am going to process is a mapping.

I am trying to do somehting like this :

contract Original {

mapping(bytes32 => Person) private Persons;

 /* many structs and methods here */
}

contract SecondContract {
   function processdata(){
     /* here i want to process the data stored in the mapping in the first contract */
   }
}

how do i get the link between the two contracts and be able to process that data ?

3 Answers 3

1

Amplifying @Travis's answer.

This line

Original original;

adds considerable size to SecondContract because it contains Original.

That's a separate issue that can be solved with an interface. SecondContract doesn't require the complete bytecode for Original. That is repetitive and unnecessary. It only needs the function signature and address of the instance to talk to.

There are some tricky inheritance and type-casting concerns to untangle so that SecondContract can inherit the smallest possible representation of Original's surface area (but not the working code) and both contracts can be in perfect sync about the layout of the Person. I decided to take a stab at it for you. You can extrapolate from that to a more complex situation.

SecondContract will be much smaller because the interfaces it inherits will never grow very large.

pragma solidity 0.8.1;

interface Types {
  struct Person {
    uint age;
    string name;
  }    
}

interface IOriginal is Types {
  function persons(bytes32) external view returns(uint, string memory);
}

contract Original is IOriginal {
  mapping(bytes32 => Person) public override persons;
}

contract SecondContract is Types {
  IOriginal original;

  constructor(address ofOriginalContract) {
    original = IOriginal(ofOriginalContract);
  }

  function processData(bytes32 someBytes) public {
    (uint age, string memory name) = original.persons(someBytes);
    // do something with entry
  }
}

It would be more satisfying if function persons() returned a Person instead of the members in the struct but I didn't get it to work. Perhaps a kind soul will chime in with a solution for that.

Hope it helps.

0

If I understand correctly, you just want to access the data stored in Original. If that's the case, you can do something like this:

contract Original {
  mapping(bytes32 => Person) public persons;
}

contract SecondContract {
  Original original;

  function SecondContract(address ofOriginalContract) {
    original = Original(ofOriginalContract);
  }

  function processData(bytes32 someBytes) {
    Person entry = original.persons[someBytes];
    // do something with entry
  }
}

Notice that I made persons a public mapping, so we can access it from another contract.

1
  • That is something i did already, but the problem that i can't add anything more to my contract, because it will not get deployed on the ganache-cli (due to size). so adding a second contract next to the original contract won't be different from adding processData function to the original contract Commented Mar 6, 2018 at 7:43
0

Maybe u can do it with delegatecall and assembly: enter a function's selector and it will delegatecall. U can write any logic u want in the SecondContract while it will execute in Original.

pragma solidity ^0.8.0;

contract Original {
    struct Person {
        uint age;
        string name;
    }

    uint256 public x = 0;
    address public secondContract; 
    mapping(bytes32 => Person) private Persons;

    constructor(address _addr) public {
        secondContract = _addr;
    }

    fallback() external {
        bytes4 _selector;
        assembly {
            // get the function's selector
            calldatacopy(0x0, 0, 4)
            _selector := mload(0x0)
        }
        // delecgatecall: for example, u can modify 'x'
        secondContract.delegatecall(abi.encodePacked(_selector)); // low level interactions input: 0x57e7c8c2
    }
}


contract SecondContract {
    struct Person {
        uint age;
        string name;
    }

    uint256 public x = 0;
    address public secondContract; 
    mapping(bytes32 => Person) private Persons;

    function processdata1() public {
        // for example, u can modify 'x'
        x = 1;
    }
    function processdata2() public {
        // do somethin u want
    }
    function processdata3() public {
        // do somethin u want
    }
    function getHash() public pure returns(bytes4){
        return bytes4(keccak256(abi.encodePacked("processdata1()"))); // 0x57e7c8c2
    }

}

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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