[Ethereum] How to use a proxy contract with ethers.js

ethers.jsproxy-contractssolidity

I'm trying to test a contract via a proxy, but I don't know how to create an instance of a the contract proxy to call the delegate functions.
I'm using typescript, ethers.js with hardhat

The contract Adder have two function called addOne and theCounter which adds one and returns the current value of the counter respectively.
how can I call addOne on the proxy contract so the fallback function fires?
here is the test I'm trying to write :

import {expect} from 'chai'
import {ethers} from 'hardhat';

describe("Proxy", () => {
  it("should call addOne on delegate", async () => {
    const Delegate = await ethers.getContractFactory("Adder"); 
    const Proxy = await ethers.getContractFactory("Proxy"); 

    let adder = await Delegate.deploy(0);
    let proxy = await Proxy.deploy();

    await adder.deployed();
    await proxy.deployed();

    await proxy.functions.upgradeDelegate(adder.address);

    // TODO : how can I call the function addOne() on proxy???

    expect(await adder.theCounter()).to.equal(1);
    
  })
});

this is the code of the proxy:

pragma solidity <0.8.0;

// SPDX-License-Identifier: MIT

contract Proxy {

    address delegate;
    address owner = msg.sender;

    function upgradeDelegate(address newDelegateAddress) public {
        require(msg.sender == owner);
        delegate = newDelegateAddress;
    }

    fallback() external {
        assembly {
            let _target := sload(0)
            calldatacopy(0x0, 0x0, calldatasize())
            let result := delegatecall(gas(), _target, 0x0, calldatasize(), 0x0, 0)
            returndatacopy(0x0, 0x0, returndatasize())
            switch result case 0 {revert(0, 0)} default {return (0, returndatasize())}
        }
    }
}

and the adder:

pragma solidity <0.8.0;

// SPDX-License-Identifier: MIT

contract Adder {
    uint public counter;

    constructor(uint init) {
        counter = init;
    }

    function addOne() public returns (uint) {
        counter++;
        return counter;
    }

    function theCounter() public view returns (uint) {
        return counter;
    }


}

Best Answer

I used attach to call the implementation functions from my proxy contract:

adder = Delegate.attach(proxy.address) as Delegate
Related Topic