1

I am trying to implement a proxy pattern. I have a proxy contract and a lottery contract, and I would like the proxy contract to delegate calls to the lottery contract.

To test that the function calls are being delegated, I wanted to call enter() to enter a player into the lottery and call getPlayers() to check that the number of players in the lottery was equal to 1.

The mocha test for this is as follows:

  it('allows one account to enter', async () => {

       await proxy.methods.enter().send({
           from: accounts[1],
           value: web3.utils.toWei('0.02', 'ether')
       });

       const players = await proxy.methods.getPlayers().call({
           from: accounts[0]
       });

       assert.equal(accounts[1], players[0]);
       assert.equal(1, players.length);
   })

The proxy contract has a fallback function that delegates calls to the lottery contract. By calling enter() and getPlayers() on the proxy contract, I was hoping that the function signatures would not be recognised and instead the fallback function would be called.

However, its not working. I get the type error: TypeError: proxy.methods.enter is not a function.

Why is the fallback function not being called? I thought that the point of a fallback function was to be called if other the functions do not equal the provided identifier.

Is there a better way (or a correct way if I am doing this completely wrong) to test whether the calls are being delegated.

I've put the fallback function for the proxy contract below in case its helpful:

function () external payable {

    address target = getLotteryAddress();


    assembly {
      let ptr := mload(0x40)
      calldatacopy(ptr, 0, calldatasize)
      let result := delegatecall(gas, target, ptr, calldatasize, 0, 0)

      let size := returndatasize
      returndatacopy(ptr, 0, size)

      switch result
      case 0 { revert(ptr, size) }
      case 1 { return(ptr, size) }
    }
  }
eth
  • 85,679
  • 53
  • 285
  • 406
Liv Stan
  • 181
  • 5
  • I think you want to use web3js .call like https://ethereum.stackexchange.com/questions/11856/how-to-detect-from-web3-if-method-exists-on-a-deployed-contract Please post your answer if you get it :) – eth Sep 05 '19 at 03:14
  • How do you create your proxy object? – Ismael Sep 06 '19 at 17:18

2 Answers2

1

Answering the question in the title (How to test a custom fallback function using web3.js?):

await web3.eth.sendTransaction({
    from: accounts[1],
    to: proxy.address,
    value: web3.utils.toWei('0.02', 'ether')
});

I'm assuming that accounts[1] is unlocked on the node that you're connected to.

goodvibration
  • 26,003
  • 5
  • 46
  • 86
1

Web3js contracts use the ABI to know how to make calls to contract functions, it needs parameters and types to properly encode it. If you try to call a function that is not present in the ABI it will complain about missing function.

You have two possible solutions:

  1. Use a contract with the correct ABI but use proxy address instead.

  2. Use sendTransaction and encodeABI to correctly format parameters and types.

Ismael
  • 30,570
  • 21
  • 53
  • 96