Here is my code

contract SimpleUpgrade {
  address public implementation;
  address public admin;
  string public words;

  constructor(address _implementation) {
    admin = msg.sender;
    implementation = _implementation;

  fallback() external payable {
    (bool success, bytes memory data) = implementation.delegatecall(msg.data);

  function upgrade(address newImplementation) external {
    require(msg.sender == admin);
    implementation = newImplementation;

contract Logic1 {
  address public implementation;
  address public admin;
  string public words;

  function overrideWords() public {
    words = 'old';

  function getWords() public view returns (string memory) {
    return words;

And after deployed them on bsc testnet, I would like to trigger overrideWords vie hardhat console. Here are my oprations:

> var SimpleTracker = await ethers.getContractFactory('SimpleUpgrade')
> var st = SimpleTracker.attach('0x910dd384e42BF33463AB1242Cf7189BCe7C3EEBE')  // Logic1 contract address on bsc testnet

And then I can get the address of Logic1 via

await st.admin()
> '0xec129bBB52925906BF1920a9Be7935C41C768A2C'

but not able to call overrideWords

> await st.overrideWords()
Uncaught TypeError: st.overrideWords is not a function

What should I do?

2 Answers 2


You can't simply call a function from the implementation interface on the SimpleUpgrade instance because it doesn't know how to handle that method.

If you want to have the same behaviour, I've created a simple script to do that:

const { Signer } = require("ethers");
const { ethers } = require("hardhat");

const overrideWordsABI = [
    inputs: [],
    name: "overrideWords",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",

async function main() {
  const SimpleUpgradeFactory = await ethers.getContractFactory("SimpleUpgrade");
  const SimpleUpgrade = SimpleUpgradeFactory.attach("0x910dd384e42BF33463AB1242Cf7189BCe7C3EEBE");

  const Logic1Address = SimpleUpgrade.implementation();
  const Logic1Factory = await ethers.getContractFactory("Logic1");
  const Logic1 = Logic1Factory.attach(Logic1Address);

  const iface = new ethers.utils.Interface(overrideWordsABI);
  const overrideWordsData = iface.encodeFunctionData("overrideWords");

  const [deployer] = await ethers.getSigners();
  const signer = ethers.provider.getSigner(deployer.address);

  const tx = await signer.sendTransaction({
    to: SimpleUpgrade.address,
    data: overrideWordsData,
    gasLimit: 30000000
  await tx.wait();
  words = await SimpleUpgrade.words();
  console.log("words: ", words);

main().catch((error) => {
  process.exitCode = 1;
  • It works! Really appreciate!!
    – Corbin_Guo
    Commented Apr 9, 2023 at 13:38
    var SimpleTracker = await ethers.getContractFactory('SimpleUpgrade')

    var st = SimpleTracker.attach('0x910dd384e42BF33463AB1242Cf7189BCe7C3EEBE');
    await st.overrideWords();

You are trying to call overrideWords() which is a function from Logic1 contract on the SimpleUpgrade contract

To call this function, you must interact with the Logic1 contract by calling this function from the SimpleUpgrade contract's proxy.

  • I did the same thing but it didn't work. It reported error "Uncaught TypeError: st.overrideWords is not a function"
    – Corbin_Guo
    Commented Apr 9, 2023 at 12:30

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.