My smart contract is calling other smart contract's function, which has inside require(msg.sender != tx.origin, "OneSplit: do not send ETH directly"); function.

I do not understand why is it failing on this specific line. As far as I understand, msg.sender should be my smart contract and tx.origin should be my wallet used to sign the transaction, so they should differ.

Am I mistaken? Why are those two the same then?


I am trying to use 1inchProtocol's OneSplit contract to swap tokens with the best rate possible, involving even multiple DEXes.

(see: https://github.com/1inch/1inchProtocol)

This is the contract I am trying to connect to:


And this is my implementation:


abstract contract IOneSplit { // interface for 1inch exchange.
    function getExpectedReturn (
        IERC20 fromToken,
        IERC20 toToken,
        uint256 amount,
        uint256 parts,
        uint256 disableFlags
            uint256 returnAmount,
            uint256[] memory distribution

    function swap(
        IERC20 fromToken,
        IERC20 toToken,
        uint256 amount,
        uint256 minReturn,
        uint256[] memory distribution,
        uint256 disableFlags
    ) public virtual payable;


contract MyContract is ICallee {

    // OneSplit Config
    address ONE_SPLIT_ADDRESS = 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E;
    uint256 PARTS = 10;
    uint256 FLAGS = 0;
    // trade function
    function _trade(address _fromTokenAddress, address _toTokenAddress, uint256 _amount, uint8 _slippage_from, uint8 slippage_to) internal {
        // Swap on 1Split
        _oneSplitSwap(_fromTokenAddress, _toTokenAddress, returnAmount_1, returnAmount_calc, 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, _amount);

        // Swap tokens: give _from, get _to
        // Following line should basicly just use .swap() function from OneSplit protocol
        // OneSplit is "forwarding" the transaction to OneSplitAudit.sol where it fails on line 75 - See: https://github.com/1inch/1inchProtocol/blob/master/contracts/OneSplitAudit.sol
        _oneSplitContract.swap(_fromIERC20, _toIERC20, _amount, _minReturn, _distribution, FLAGS);

        // Reset approval
        _fromIERC20.approve(ONE_SPLIT_ADDRESS, 0);

And this is my failed transaction:


It says "Fail with error 'OneSplit: do not send ETH directly'" which is located in OneSplitAudit.sol. So this is how I determined what is failing.

  • Is your contract calling the other contract with delegateCall?
    – Undead8
    Jul 20 '21 at 20:01
  • I kind of do not know what delegateCall is. I am rather new to solidity dev. I used abstract virtual class to access some functions of other contract from inside my contract.
    – LubWn
    Jul 20 '21 at 20:55
  • You should edit your question to post a link to the contract code and a link to the transaction that failed. I am not sure that the answer from Joel is correct.
    – Undead8
    Jul 20 '21 at 23:34
  • Edited. I guess I have badly implemented inheritance from other contract? Because in etherscan I can see my wallet is communicating with contract, not my contract itself.
    – LubWn
    Jul 21 '21 at 0:21

The problem is with your transaction.

Here is what your transaction did wrong:

  • Your transaction does nothing besides sending Eth to the to address.
  • The to address (ie. the contract that you are calling directly) is this contract. I am not sure if it is intended or not.
  • Your transaction does not call any known function of the to contract.

Because you are sending Eth and not calling any particular known function, the OneSplitAudit contract will execute its fallback function. This fallback function is specifically designed to revert in that case, so that EOA cannot blindly send Eth to the contract, where it would be irrecoverable (looks like it worked as intended in your case!). Here is the code of the fallback function:

function() external payable {
    require(msg.sender != tx.origin, "OneSplit: do not send ETH directly");

I can't really suggest you a fix because I don't know what you are trying to do (what function you want to call of which contract).

  • I was trying to call .swap() function of the 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E contract, which should call the contract in your answer. Am I doing it wrong? I am trying to send ETH and swap it to other token.
    – LubWn
    Jul 21 '21 at 0:39
  • It seems that there is an issue with your transaction, yes. You should post a new question and include the code that sends the transaction.
    – Undead8
    Jul 21 '21 at 2:35
  • It is there, I mean the line _oneSplitContract.swap(_fromIERC20, _toIERC20, _amount, _minReturn, _distribution, FLAGS); in _oneSplitSwap function. Rest of the contract contains nothing too relevant. I can post the whole contract if needed but I think the problem is somewhere in those lines.
    – LubWn
    Jul 21 '21 at 2:38
  • Your failed transaction does not call your contract. It calls the 0xC586 contract directly, and it seems to not call it correctly. How do you send that transaction? Web3js? Remix? We need to see how your transaction is built to see why it is built wrong.
    – Undead8
    Jul 21 '21 at 12:26
  • Oh I am so stupid!!!! Now I understand THANK YOU very much! I was calling the 0xC586 contract by accident, I copied wrong address instead of mine contract. The whole other code was right I just copied wrong address in web3.
    – LubWn
    Jul 21 '21 at 14:34

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.