The Proxy model

These days, I am trying to use the Proxy model, I find that if my original contract is a single contract,
that is this original contract does not interact with others, it is OK, it can work well with the Proxy
model. But if my original contracts are multiple files, that is one contract will interact with another,
you can see an example below:

contract Logic {
    Store s;
    uint256 private logicValue;
    constructor (address dataAddr) public {
        s = Store(dataAddr);
    }
    
    function delegateGet() public view returns(uint256) {
        return s.getValue();
    }
    
    function delegateSet(uint256 value) public {
        s.setValue(value);
    }
    
    function canGet() public view returns (uint256) {
        return logicValue;
    }
    function canSet(uint256 value) public {
        logicValue = value;
    }
}
contract Store {
    uint256 public dataValue;
    
    function getValue() public view returns (uint256) {
        return dataValue;
    }
    
    function setValue(uint256 newValue) public {
        dataValue = newValue;
    }
}

With the proxy, I can call the function of canGet() and canSet() in the Logic contract, but
I can not call the function of delegateGet() and delegateSet(). So, in such case, how can I use
the Proxy model? or does the Proxy model not support this case?

2 Likes

I assume when you use the Proxy instead of having a constructor in the Logic contract you have an Initialize function and inherit from Initializable?

I deployed the Store contract in truffle console and then initialized the Logic contract
npx zos create Logic --init initialize --args ADDRESS-OF-DEPLOYED-STORE
(Setting up my project using the following instructions: https://docs.zeppelinos.org/docs/deploying.html)

I was then able to use canSet and canGet, as well as delegateSet and delegateGet in truffle console.

Store contract

contract Store {
    uint256 public dataValue;
    
    function getValue() public view returns (uint256) {
        return dataValue;
    }
    
    function setValue(uint256 newValue) public {
        dataValue = newValue;
    }
}

Logic contract (updated to be Initializable)

pragma solidity ^0.5.0;

import "./Store.sol";
import "zos-lib/contracts/Initializable.sol";

contract Logic is Initializable {
    Store s;
    uint256 private logicValue;
    function initialize (address dataAddr) public initializer {
        s = Store(dataAddr);
    }
    
    function delegateGet() public view returns(uint256) {
        return s.getValue();
    }
    
    function delegateSet(uint256 value) public {
        s.setValue(value);
    }
    
    function canGet() public view returns (uint256) {
        return logicValue;
    }
    function canSet(uint256 value) public {
        logicValue = value;
    }
}
2 Likes

Emmm, you can? Maybe I use something mistakenly. I will look at that instructions, thanks!

1 Like

Let me know if you have any issues and I can provide more details of how I deployed.


Also, please note by creating Store as per the above, even though Logic is upgradeable, Store is not.

There is an example of how to create upgradeable contracts via a factory:

https://github.com/zeppelinos/zos/tree/master/examples/creating-instances-from-solidity

Yeah, I am really have some confusion with this model, and the opcode delegatecall, but I will try first, and then ask here for my confusion. Thanks!

1 Like

In this example, the main thing is that the upgradable contract has an initialize function and doesn’t have a constructor.

Keep asking questions, and let me know how you get on.

1 Like

Yeah, you are right. I have tried following that document, and everyting worked well,
so I did make some mistake. Ok, I have some confusion:

  • As far as I know, when we try to use the opcode delegatecall, it means that
    if A delegatecall B, the code of B is executed on the storage A with the original msg.sender,
    so with the Proxy model, does that mean all data are saved in the Proxy contract?
  • In my case, I need to record two token balances, so I use two data contracts and a common logic contract(The practical case is POA token bridge contract, one contract records the amount of depositing DAI, and the amount of genetating xDAI), so if all data are save in the Proxy contract, is it OK? will there be any conflict?
  • If I deploy it on the testnet, how can I verify my contracts, you know, I import some contract,
    such as zos-lib/contracts/Initializable.sol, so should I find out the original contract in the node_module?
1 Like

Hi @Skyge

Suggest you have a read through the following:

For verification, do you mean on Etherscan?
You can use zos verify

Yeah, this article is really helpful. Thanks a lot!

1 Like

Some housekeeping, I have moved the topic to #support:zeppelinos category and marked my first reply as the solution to your original question.

Yeah, that is right!

1 Like