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) }
    }
  }
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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.