2

While working on integrating the Balancer Exchange protocol in my project, I noticed this interface defined in their exchange proxy:

interface TokenInterface {
    function balanceOf(address) external view returns (uint);
    function allowance(address, address) external view returns (uint);
    function approve(address, uint) external returns (bool);
    function transfer(address, uint) external returns (bool);
    function transferFrom(address, address, uint) external returns (bool);
    function deposit() external payable;
    function withdraw(uint) external;
}

This is almost an ERC-20 interface, but it has two custom functions, deposit and withdraw. The reason why these functions exist is out of scope for this question.

I want to call this function on the exchange proxy:

function smartSwapExactIn(
    TokenInterface tokenIn,
    TokenInterface tokenOut,
    uint256 totalAmountIn,
    uint256 minTotalAmountOut,
    uint256 nPools
) external payable returns (uint256 totalAmountOut);

But I would like to use a vanilla ERC-20 interface instead of this custom TokenInterface when writing my contract.

Here is the tricky part. Balancer has already deployed the exchange proxy at address 0x3E66B66Fd1d0b02fDa6C811Da9E0547970DB2f21. I will do the same thing with my own contract (deploy it at some point), and obviously the compiler won't complain because I used another interface instead of TokenInterface (it can't know what its eventual purpose is).

Will the the protocols "cross swords" when I attempt to call Balancer's smartSwapExactIn function via a contract that defines an interface that is slightly different to TokenInterface for the tokenIn and tokenOut arguments?

1

Yes, the protocols will cross swords if the TokenInterface is not exactly the same.

I had to use the interface as defined in the Balancer repo:

interface TokenInterface {
    function balanceOf(address) external view returns (uint256);

    function allowance(address, address) external view returns (uint256);

    function approve(address, uint256) external returns (bool);

    function transfer(address, uint256) external returns (bool);

    function transferFrom(
        address,
        address,
        uint256
    ) external returns (bool);

    function deposit() external payable;

    function withdraw(uint256) external;
}

4
  • At compile time they should conflict, at runtime if neither deposit nor withdraw are called it might work.
    – Ismael
    Mar 6 at 22:11
  • Quite the opposite. At compile, it worked. At runtime, it didn't work even if neither deposit nor withdraw were called. Mar 7 at 8:42
  • Interesting. Do you know if the compiler does an extra validation? Thanks I'll try to investigate the reason.
    – Ismael
    Mar 7 at 17:15
  • 1
    I don't know about any extra validation. I used v0.7.6 to compile my project. But I am sure that my answer is correct, that is, I had to use Balancer's token interface lest the execution reverted. Mar 8 at 10:17

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.