I am trying to use OneSplitProtocol (0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E) to swap some ETH for ChainLink token at a better price. I set up HardHat enviroment with mainnet fork for testing purposes.
When I try to execute swap() function on OneSplit contract I get "SafeERC20: low-level call failed" error. I tracked down the error to SafeERC20 contract provided by OpenZeppelin but I am pretty sure my implementation is wrong, but the error is rather confusing and I have no idea where the problem lies.
At first I thought the problem lies with approval of tokens owned by contract but by testing all the possibilities of approvals I figured out this is probably not the problem.
What does the provided error actually mean? I am trying to understand what went wrong.
Code to reproduce
I am calling my contract from web3, the contract should call OneSplitProtocol contract and all the logic behind it. I am calling OneSplitProtocol contract in my contract code like this:
interface IOneSplit { // interface for 1inch exchange.
function swap(
IERC20 fromToken,
IERC20 toToken,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256 disableFlags
) external payable;
}
contract MyContract {
address ONE_SPLIT_ADDRESS = 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E;
uint256 PARTS = 10;
uint256 FLAGS = 0;
function _trade(address _fromTokenAddress, address _toTokenAddress, uint256 _amount, uint256 toTokenMinAmount, uint256[] memory distribution_1) internal {
// account in 1% slippage
uint returnAmount_calc = toTokenAmount / 100 * 99;
// Swap on 1Split
_oneSplitSwap(_fromTokenAddress, _toTokenAddress, _amount, toTokenMinAmount, distribution_1);
}
function _oneSplitSwap(address _from, address _to, uint256 _amount, uint256 _minReturn, uint256[] memory _distribution) internal {
// Setup contracts
IERC20 _fromIERC20 = IERC20(_from);
IERC20 _toIERC20 = IERC20(_to);
IOneSplit _oneSplitContract = IOneSplit(ONE_SPLIT_ADDRESS);
// Approve tokens
_fromIERC20.approve(ONE_SPLIT_ADDRESS, uint(-1));
console.log("Token Approved");
// Swap tokens: give _from, get _to
_oneSplitContract.swap(_fromIERC20, _toIERC20, _amount, _minReturn, _distribution, FLAGS);
_fromIERC20.approve(address(ONE_SPLIT_ADDRESS), 0);
}
}
I was thinking whether my implementation of interface IOneSplit is not wrong and that causes the issue. Pretty much not sure where to look at.
Code stops at "Token Approved" and fails exactly at _oneSplitContract.swap() function with "SafeERC20: low-level call failed" error.
How can I debug further or know what is failing? I am sending ETH as WETH and second argument is Chainlink token address.
Environment
Hardhat fork mainnet