1

I was trying to play with proxy pattern. But got stuck with this error.

Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="admin()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)

Proxy Contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "./CounterV1.sol";

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

contract Proxy is Initializable {
    bytes32 private constant IMPLEMENTATION_SLOT = bytes32(uint(keccak256("eip1967.proxy.implementation")) - 1);
    bytes32 private constant ADMIN_SLOT = bytes32(uint(keccak256("eip1967.proxy.admin")) - 1);

    event AdminChanged(address admin);

    // constructor() {
    //     _setAdmin(msg.sender);
    // }

    function initialize() public initializer {
        _setAdmin(msg.sender);
    }

    modifier ifAdmin() {
        if (msg.sender == _getAdmin()) {
            _;
        } else {
            _fallback();
        }
    }

    function _getAdmin() private view returns (address) {
        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
    }

    function _setAdmin(address _admin) private {
        require(_admin != address(0), "admin = zero address");
        StorageSlot.getAddressSlot(ADMIN_SLOT).value = _admin;
    }

    function getAddSelector(uint value) public pure returns (bytes memory) {
        return abi.encodeWithSelector(CounterV1.addToCount.selector, value);
    }

    function _getImplementation() private view returns (address) {
        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
    }

    function _setImplementation(address _implementation) private {
        require(_implementation.code.length > 0, "implementation is not contract");
        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation;
    }

    // Admin interface //
    function changeAdmin(address _admin) external ifAdmin {
        _setAdmin(_admin);
        emit AdminChanged(_admin);
    }

    function upgradeTo(address _implementation) external ifAdmin {
        _setImplementation(_implementation);
    }

    function admin() external view returns (address) {
        return _getAdmin();
    }

    function implementation() external ifAdmin returns (address) {
        return _getImplementation();
    }

    // User interface //
    function _delegate(address _implementation) internal virtual {
        assembly {

            calldatacopy(0, 0, calldatasize())

            let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)

            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    function _fallback() private {
        _delegate(_getImplementation());
    }

    fallback() external payable {
        _fallback();
    }

    receive() external payable {
        _fallback();
    }
}

Implementation Script

const { ethers, network } = require("hardhat")
const contractAddresses = require("../Constants/contract-addresses.json")
require("dotenv").config()

async function ChangeAdmin() {
    const chainId = network.config.chainId.toString()
    const proxy = await ethers.getContractAt("Proxy", contractAddresses[chainId]["Proxy"])
    console.log("Proxy address is :", proxy.address)

    const txReceipt = await proxy.admin()
}

function main() {
    ChangeAdmin()
}

Error in terminal:

Proxy address is : 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9

E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\logger\src.ts\index.ts:269 const error: any = new Error(message); ^

Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="admin()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0) at Logger.makeError (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\logger\src.ts\index.ts:269:28) at Logger.throwError (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\logger\src.ts\index.ts:281:20) at Interface.decodeFunctionResult (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\abi\src.ts\interface.ts:427:23)
at Contract. (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\contracts\src.ts\index.ts:400:44) at step (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\contracts\lib\index.js:48:23) at Object.next (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\contracts\lib\index.js:29:53) at fulfilled (E:\Learn_blockchain\ProxyPattern-new\node_modules@ethersproject\contracts\lib\index.js:20:58) at processTicksAndRejections (node:internal/process/task_queues:95:5) at runNextTicks (node:internal/process/task_queues:64:3) at listOnTimeout (node:internal/timers:540:9) error Command failed with exit code 1.

This is my package.json file

{
    "version": "0.0.1",
    "description": "This is to test proxy pattern",
    "main": "index.js",
    "license": "MIT",
    "devDependencies": {
        "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13",
        "@nomiclabs/hardhat-etherscan": "^3.0.0",
        "@nomiclabs/hardhat-waffle": "^2.0.1",
        "@openzeppelin/contracts-upgradeable": "^4.8.2",
        "chai": "^4.3.4",
        "dotenv": "^16.0.3",
        "ethereum-waffle": "^3.4.0",
        "ethers": "^5.5.1",
        "fs": "^0.0.1-security",
        "hardhat": "^2.13.1",
        "hardhat-contract-sizer": "^2.4.0",
        "hardhat-deploy": "^0.9.29",
        "hardhat-gas-reporter": "^1.0.7",
        "hardhat-tracer": "^2.2.2",
        "path": "^0.12.7",
        "prettier": "^2.8.4",
        "prettier-plugin-solidity": "^1.1.3",
        "solhint": "^3.3.6",
        "solidity-coverage": "^0.8.2"
    },
    "dependencies": {
        "@openzeppelin/hardhat-upgrades": "^1.22.1"
    }
}

Please help me with the error. Thank a lot!!

1 Answer 1

1

It looks like error is caused by the admin() function because its not being properly handled by proxy contract. To resolve this, modify admin() function in the Proxy contract to include ifAdmin modifier.

Update it as follows:

function admin() external ifAdmin returns (address) {
    return _getAdmin();
}
2
  • why does adding ifAdmin modifier solve the issue, i am also getting same error from other contract... Commented Apr 11, 2023 at 13:27
  • Here in this contract: contract myContract{address public owner; constructor() { owner = msg.sender; } } if i try to access the owner variable, iam getting Error: call revert exception (method="getProxyAdmin(address)", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0){ reason: null, code: 'CALL_EXCEPTION', method: 'getProxyAdmin(address)', data: '0x', errorArgs: null, errorName: null, errorSignature: null, address: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9', Commented Apr 11, 2023 at 13:27

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.