How to write tests for "msg.sender" being a contract?

I want to write unit-test (using ethers.js on top of an hardhat-project) that covers a hook-function for OpenZeppelin's ERC1155 contract: onERC1155Received.

The special thing here is that the msg.sender of this function will be the original Token contract, that calls the transfer-method which executes eventually the onERC1155Received method.

How can I make the msg.sender being a contract instead of a normal user-account?

Let's say, the Contract has code like this:

function onERC1155Received(
    address operator,
    address from,
    uint256 tokenId,
    uint256 amount,
    bytes memory data
) public virtual override returns (bytes4) {
    address originalToken = msg.sender;
    
    if (!isTokenSupported(originalToken)) {
        revert ErrWrongToken(originalToken);
    }

How can I inject an appropriate msg.sender here that reflects a token-contract?

When I want to use a special signer on a contract, I do:

const signer = token.connect(mySignerAccount);

But I can not use the same approach to use a contract-instance here as signer-account.

Any ideas how to achieve that?

Hey @oxuw4
you can override the "from" parameter

1 Like

I found a brilliant approach on Stackexchange which uses impersonateAccount-helper function:

await helpers.impersonateAccount(contractAddress);
const contractSigner = await ethers.getSigner(contractAddress);
await token.connect(contractSigner).onERC1155Received(...)

This works perfectly and exact the way I want.

1 Like