How to test methods with the same name but different parameters

Is it possible to test methods with the same name but different parameters?

If so, how do I do it?

:computer: Environment

  "dependencies": {
    "@openzeppelin/cli": "^2.8.2",
    "@openzeppelin/contracts-ethereum-package": "^3.0.0",
    "bn.js": "^5.1.3",
    "truffle": "^5.1.45",
    "web3": "^1.2.11"
  },
  "devDependencies": {
    "@openzeppelin/contracts": "^3.2.0",
    "@openzeppelin/test-environment": "^0.1.5",
    "@openzeppelin/test-helpers": "^0.5.6",
    "chai": "^4.2.0",
    "mocha": "^8.1.3"
  },

:memo:Details

I am inheriting ERC20UpgradeSafe to create a custom token.
I have added another transfer method with different parameters to the contract.
However, when I run a test using the OZ test, it only recognizes one method not the other.

:1234: Code to reproduce

await this.token.transfer(a, b, { from: deployer });

await this.token.transfer(a, b, c, d, e, f, { from: deployer });

The second line results with below:

Error: Invalid number of parameters for "transfer". Got 7 expected 2!
1 Like

Hi @taelimoh,

Welcome to the community :wave:

It is possible to test overloaded functions by using [contract].methods['functionSignature']

As an example we can send a transaction to the following function

transfer(address recipient, uint256 amount, uint256 x, uint256 y) public virtual returns (bool)

Using:

await this.token.methods['transfer(address,uint256,uint256,uint256)'](other, amount, x, y, {from: creator});

I have created a sample contract and test below:

SimpleToken.sol

// contracts/SimpleToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";

/**
 * @title SimpleToken
 * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` functions.
 */
contract SimpleToken is Initializable, ERC20UpgradeSafe {

    event TransferXY(uint256 x, uint256 y);

    function initialize(address creator) public initializer {
        __Context_init_unchained();
        __ERC20_init_unchained("SimpleToken", "SIM");
        _mint(creator, 10000 * (10 ** uint256(decimals())));
    }

    function transfer(address recipient, uint256 amount, uint256 x, uint256 y) public virtual returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        emit TransferXY(x, y);
        return true;
    }
}

SimpleToken.test.js

Test implementation contract

// test/SimpleToken.test.js

// Load dependencies
const { accounts, contract } = require('@openzeppelin/test-environment');
const { BN, expectEvent } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');

// Load compiled artifacts
const SimpleToken = contract.fromArtifact('SimpleToken');

// Start test block
describe('SimpleToken', function () {
  const [ creator, other ] = accounts;

  beforeEach(async function () {
    // Deploy a new SimpleToken contract for each test
    this.token = await SimpleToken.new({ from: creator });
    await this.token.initialize(creator);
  });

  // Test case
  it('transfer amount to other account', async function () {
    const amount = new BN('42');
    const receipt = await this.token.transfer(other, amount, {from: creator});
    expect(await this.token.balanceOf(other)).to.be.bignumber.equal(amount);
    expectEvent(receipt, 'Transfer', { from: creator, to: other, value: amount });
  });

  it('transfer amount to other account', async function () {
    const amount = new BN('42');
    const x = new BN('1');
    const y = new BN('2');
    const receipt = await this.token.methods['transfer(address,uint256,uint256,uint256)'](other, amount, x, y, {from: creator});
    expect(await this.token.balanceOf(other)).to.be.bignumber.equal(amount);
    expectEvent(receipt, 'Transfer', { from: creator, to: other, value: amount });
    expectEvent(receipt, 'TransferXY', { x: x, y: y });
  });
});

As an aside, if you are using Truffle, you could look at using OpenZeppelin Upgrades Plugins.
Documentation: https://docs.openzeppelin.com/upgrades-plugins/1.x/
Tutorial: OpenZeppelin Truffle Upgrades: Step by Step Tutorial

OpenZeppelin Test Helpers includes a bn.js object: https://docs.openzeppelin.com/test-helpers/0.5/api#bn

Hi @taelimoh,

I wanted to check if the above solved your question? If it did, can you mark it as the solution please?

Otherwise feel free to ask all the questions that you need.

Hi @abcoathup,

Your suggestion worked.

For future reference, functionSignature should not have any space.

As an example, below throws a TypeError

await this.token.methods['transfer(address, uint256, uint256, uint256)'](other, amount, x, y, {from: creator});
TypeError: this.token.methods.transfer(address, uint256, uint256, uint256) is not a function
1 Like