Trouble using ProxyAdminProject class from Upgrades

I am trying to set up a ProxyAdmin project using the SDK (rather than CLI) as i have requirements i cannot meet with the CLI. The “usage” documentation on the projects GIT simply do not work correctly.

ZWeb3.initialize(web3.currentProvider);


this.project = new ProxyAdminProject('MyProject', { from: await ZWeb3.defaultAccount(), gas: 1e6, gasPrice: 1e9 });

gives the error
"Contract or address expected"

after looking through the upgrades code i see the constructor takes 4 params so i try this

    ZWeb3.initialize(web3.currentProvider);

    this.project = new ProxyAdminProject('MyProject', null, null, { from: await ZWeb3.defaultAccount(), gas: 1e6, gasPrice: 1e9 });

    const GeneralUserV0 = Contracts.getFromLocal('GeneralUser');
    const instance1 = await this.project.createProxy(GeneralUserV0);
    const instance2 = await this.project.createProxy(GeneralUserV0);

    const GeneralUserV2 = Contracts.getFromLocal('GeneralUserV2')
    await this.project.upgradeProxy(this.contractAddressUser1, GeneralUserV2)

at this point the createProxy contracts deploy properly (i tested calling the contracts using web3) however when i try to upgrade the contracts i get “out of gas” which i find odd (unsure how the contracts got deployed when the admin account has 0 eth, please read on for explanation)

So i then check the “Proxy Admin” address to find out it is null

    ZWeb3.initialize(web3.currentProvider);

    this.project = new ProxyAdminProject('MyProject', null, null, { from: await ZWeb3.defaultAccount(), gas: 1e6, gasPrice: 1e9 });

    this.progjectAdminAddress = await this.project.getAdminAddress()
    console.log("ADMIN: ", this.progjectAdminAddress); <<< NNULL

    // Create proxxy contracts for users
    const GeneralUserV0 = Contracts.getFromLocal('GeneralUser');
    const instance1 = await this.project.createProxy(GeneralUserV0);
    const instance2 = await this.project.createProxy(GeneralUserV0);

    const GeneralUserV2 = Contracts.getFromLocal('GeneralUserV2')
    await this.project.upgradeProxy(this.contractAddressUser1, GeneralUserV2)

so i then use the “ensure admin function”

    ZWeb3.initialize(web3.currentProvider);

    this.project = new ProxyAdminProject('MyProject', null, null, { from: await ZWeb3.defaultAccount(), gas: 1e6, gasPrice: 1e9 });

    await this.project.ensureProxyAdmin()
    this.progjectAdminAddress = await this.project.getAdminAddress()

    // Create proxxy contracts for users
    const GeneralUserV0 = Contracts.getFromLocal('GeneralUser');
    const instance1 = await this.project.createProxy(GeneralUserV0);
    const instance2 = await this.project.createProxy(GeneralUserV0);

    const GeneralUserV2 = Contracts.getFromLocal('GeneralUserV2')
    await this.project.upgradeProxy(this.contractAddressUser1, GeneralUserV2)

Which now gives me a proxy admin address but also gives a balance of 0 so again i obviously get “out of gas”

What is the propper way to set up a project? looking at the constructor of ProxyAdminProject i guess i have to manually instantiate an instance ProxyAdmin class and pass it into ProxyAdminProject contractor. is this correct?

I see on the GIT the API is a TODO is there anywhere i can get some sort of API documentation even if it is half baked.

EDIT: update

I forgot to metion i have also tried allocating ETH to an account and using that account as the admin also (I am passing in a full private key have just ommited for posting here, even though it isnt a key in use)

const startBlockchainServer = (port, opts) => (
    new Promise((resolve, reject) => {
        const server = ganache.server(opts);
        server.listen(port, function(err, blockchain) {
            console.log(err)
            if(err) reject(err);
            resolve(blockchain)
        });
    }))

    await startBlockchainServer(BLOCKCHAIN_PORT, {
        accounts: [
            { secretKey: "0xcce0c867c6722a02f98b482cd9bd94106eaf56fb3c2dd666ff...", balance: 10000000000000000000 }
        ]
    });

    admin = await web3.eth.accounts.privateKeyToAccount("0xcce0c867c6722a02f98b482cd9bd94106eaf56fb3c2dd666ff...");
    ZWeb3.eth.accounts.wallet.add(admin)
    const project = new ProxyAdminProject('MyProject', null, null, { from: admin.address, gas: 1e6, gasPrice: 1e9 });

    const GeneralUserV2 = Contracts.getFromLocal('GeneralUserV2')
    project.upgradeProxy(this.contractAddressUser1, GeneralUserV2)

When i check the balance of the “admin” wallet i created i can see the amount of ETH has decreased after creating an instance of ProxyAdminProject however when i try to upgrade i still get VM Exception while processing transaction: out of gas

Thanks for the help

:computer: Environment
@openzeppelin/upgrades v2.8.0
ganache-cli v6.9.1
mocha to run tests

:memo:Details
I understand why am getting the errors i am, it’s more there is no clear was to set up a project and preform upgrades. The code in the docs simply do not work and seem out of date as the constructor takes more params than the example shows. and this class will not work without those extra params it seems.

:1234: Code to reproduce
Minimal example taken from much lager code base

const { Contracts, ProxyAdminProject, ZWeb3, ProxyAdmin, Transactions } = require('@openzeppelin/upgrades');
const ganache = require("ganache-cli");

const BLOCKCHAIN_PORT = '8545'

const startBlockchainServer = (port, opts) => (
    new Promise((resolve, reject) => {
        const server = ganache.server();
        server.listen(port, function(err, blockchain) {
            console.log(err)
            if(err) reject(err);
            resolve(blockchain)
        });
    }))


describe('Test', function () {   
    this.accounts;
    this.project;
    this.progjectAdminAddress;
    this.user1Contarct;
    this.user2Contract;
    this.web3User1ContractInstance;
    this.web3User2ContractInstance;
    this.user1EthAccount;
    this.user2EthAccount;
    this.contractAddressUser1;


    it.only('Deploy User smart contracts', async function(){
        await startBlockchainServer(BLOCKCHAIN_PORT, {});
       
 
        ZWeb3.initialize(web3.currentProvider);

        this.project = new ProxyAdminProject('MyProject', null, null, { from: await ZWeb3.defaultAccount(), gas: 1e6, gasPrice: 1e9 }).createProxy();

        // Get Admin address 
        await this.project.ensureProxyAdmin()
        this.progjectAdminAddress = await this.project.getAdminAddress()

        // Create proxxy contracts for users
        const GeneralUserV0 = Contracts.getFromLocal('GeneralUser');
        const instance1 = await this.project.createProxy(GeneralUserV0);
        const instance2 = await this.project.createProxy(GeneralUserV0);

        const GeneralUserV2 = Contracts.getFromLocal('GeneralUserV2')
        await this.project.upgradeProxy(this.instance1.address, GeneralUserV2)

    })
})
1 Like

Hi @Rick_Sanchez,

I'm very sorry about the documentation and the non-working example in the usage section of the README.

Please see the following from @frangio

From: How to create proxies programmatically during network congestion? - #12 by frangio

I’m really sorry about the lack of documentation around using upgrades programmatically from JavaScript. The existing JavaScript interface kind of evolved as the internals of the CLI, and was not optimized to be a user-facing API. This is definitely a weak point of the library, which is why we’re currently working on a redesign, announced in the Q2 Roadmap. Unfortunately I can’t share a timeline for it yet, but the project is likely going to extend into Q3.

If you’re in a position in which you need to use the current library, perhaps you’d find the example in the repo useful.


When using a ProxyAdminProject we need to provide the address of the ProxyAdmin rather than an EOA.

1 Like

The existing JavaScript interface kind of evolved as the internals of the CLI, and was not optimized to be a user-facing API

ah ok fair enough makes sense.

Thanks for the example ill just read through the library code for now. looking forward to the new library.

Thanks Again

1 Like

I checked out the example you linked too and it works fine. But when i change the contracts to contracts i have written i get Out of gas any idea why? they are only small simple contracts.

(which i guess is the same issue as i have described above, as the rest of my code above is the same as the example you have provided. I have written full tests for my contracts and they function correctly)

1 Like

Hi @Rick_Sanchez,

You could try increasing the gas:

Otherwise if you can share your contract (or a cut down version) and I can try to reproduce?