I have a test project with proxy pattern (fallback/delegate call). The purpose is to have upgradeable contracts. Here is the proxy contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import "hardhat/console.sol";
contract StorageContract {
address private implementation;
function setImplementation(address storageimplementation) external
{
implementation = storageimplementation;
}
fallback() external
{
console.log("executing fallback-------");
delegate(implementation);
}
function delegate(address a) internal
{
assembly
{
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), a, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0
{
revert(0, returndatasize())
}
default
{
return(0, returndatasize())
}
}
}
}
Implementation contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import "hardhat/console.sol";
contract StorageImplementation
{
function add(uint256 a, uint256 b) public returns (uint256)
{
console.log("add function called");
return a+b;
}
function hello() public returns (string memory)
{
console.log("hello function called");
return "hello";
}
}
Test:
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Storage", function () {
it("delegatecall test", async function () {
const StorageContract = await ethers.getContractFactory("StorageContract");
const storage = await StorageContract.deploy();
await storage.deployed();
const StorageImplementation = await ethers.getContractFactory("StorageImplementation");
const storageImpl = await StorageImplementation.deploy();
await storageImpl.deployed();
storage.setImplementation(storageImpl.address);
let impl = await storage.getImplementation();
console.log("impl:" + impl);
let helloResp = await storage.hello();
expect(helloResp).to.equal("hello");
});
});
Fallback function is not executing when I call a function that does not exist in the contract.
After executing tests via npx hardhat test I get an error:
TypeError: storage.hello is not a function
And the log message in fallback is not printed.
I have also tried using receive function and payable modifier with fallback but it didn't help.
I hope I was clear enough. Thanks in advance for any suggestions.