I am new to this topic. I'm trying to implement a method to split the payment inside the token contract itself. I know that there is a separate contract for payment splitting, but I want to try to implement it inside token contract.

I've written such a method. Could you please tell me:

  1. Is it safe to make the payment this way?
  2. Is it possible to implement in any other way (but inside token contract itself)?
    function splitPayment(address from, address firstReceiver, address secondReceiver, uint256 amount) public {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(firstReceiver != address(0), "ERC20: transfer to the zero address");
        require(secondReceiver != address(0), "ERC20: transfer to the zero address");

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");

        unchecked {
            _balances[from] = fromBalance - amount;

        _balances[firstReceiver] += amount * 70 / 100;
        _balances[secondReceiver] += amount * 30 / 100;

        emit SplittedTransfer(from, firstReceiver, secondReceiver, amount);
  • You may need a fixed-point math library if you want to accurately calculate percentages. I recommend using PRBMath (disclaimer: I'm the author). Commented Jul 12, 2022 at 16:39
  • Also: consider using custom errors instead of revert reason strings. Compared to revert reason strings, custom errors are easier to work with, more gas efficient, and more elegant. Commented Jul 12, 2022 at 16:39

2 Answers 2


Yes, It is possible. It will be better if you split payment in this way, Here You dont have to worry a lot

function splitTransfer(address firstReceiver ,address secondReceiver,  uint256 amount) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, firstReceiver, amount* 70 / 100);
        _transfer(owner, secondReceiver, amount* 30 / 100);
        return true;

This way of splitting tokens seems ok, but you need to make sure that the tokens cannot be transferred by anyone. You have two options here:

  1. Tokens can only be split by their owner
  2. Tokens can only be split by their owner or by someone that has been given allowance

Option 1 would look like this:

require(from == msg.sender, "ERC20: transfer of foreign assets");

Option 2 would look like this:

require(from == msg.sender || _allowances[from][msg.sender] >= amount, "ERC20: exceeds allowance");

If you go with option 2, you also have to make sure to update _allowances and emit the Approval event.

I think it would be better to emit 2 Transfer events instead of creating a new event, as the Transfer event is standardised.

  • Thank you for useful information) Commented Jul 13, 2022 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.