0

I have an erc20 token disperse contract. I want to modify the contract to take 1% fee on each token/eth transferred with the disperse contract.

My disperse contract

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.16;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Disperse {
    
    function disperseToken(
        IERC20 tokenAddress,
        address payable[] calldata recipients,
        uint256[] calldata values
    ) external {
        IERC20 token = IERC20(tokenAddress);
        uint256 total = 0;
        for (uint256 i = 0; i < recipients.length; i++) total += values[i];
        require(token.transferFrom(msg.sender, address(this), total));
        for (uint256 i = 0; i < recipients.length; i++) {
            token.transfer(recipients[i], values[i]);
        }
    }

    function disperseEther(address[] memory recipients, uint256[] memory values) external payable {
        for (uint256 i = 0; i < recipients.length; i++)
            payable(recipients[i]).transfer(values[i]);
        uint256 balance = address(this).balance;
        // Refund remaining amount to msg.sender
        if (balance > 0) payable(msg.sender).transfer(balance);
    }
}

1 Answer 1

1

if you just need 1% of the payment can retain in the contract just to return this back to the msg.sender, hope you won't be keeping any ether in the contract which can make this contract vulnerable.

function disperseEther(address[] memory recipients, uint256[] memory values) external payable {
      // input validations
        require(recipients.length == values.length, "Input Error");
        uint256 fullPay = 0;
        for (uint256 i = 0; i < recipients.length; i++) {
            fullPay = fullPay + values[i];    
        }
        // pay validation
        require(fullPay <= msg.value, "pay is not enough");
        for (uint256 i = 0; i < recipients.length; i++) {
            // pay only 99% of the amount remaining will be on the contract
           payable(recipients[i]).transfer((values[i]*99)/100);
        }
        uint256 balance = address(this).balance;
        // Refund remaining amount - tax to msg.sender
        if (balance > 0) payable(msg.sender).transfer(balance);
}

function disperseToken(IERC20 tokenAddress,address payable[] calldata recipients,uint256[] calldata values) external {
        IERC20 token = IERC20(tokenAddress);
         // input validations
        require(recipients.length == values.length, "Input Error");
        uint256 total = 0;
        for (uint256 i = 0; i < recipients.length; i++) total += values[i];
        require(token.transferFrom(msg.sender, address(this), (total* 99)/100));
        for (uint256 i = 0; i < recipients.length; i++) {
            token.transfer(recipients[i], (values[i]* 99)/100);
        }
        token.transfer(address(this), token.balanceOf(msg.sender));
    }
9
  • great. I have not tested it yet though. is the same mechanism for disperseToken method too?
    – PerfDev.
    Commented Dec 25, 2022 at 9:33
  • But I am not so confident with your code, seems there are so many flows, also this can be vulnerable to reentrancy attacks, also you can send a value but not enough ethers... which can drain your contract, without the logic I am not sure how to how to fix it. if you can explain the logic I think I might be able to Commented Dec 25, 2022 at 9:40
  • Error: cannot estimate gas; transaction may fail or may require manual gas limit
    – PerfDev.
    Commented Dec 25, 2022 at 9:52
  • got this error.
    – PerfDev.
    Commented Dec 25, 2022 at 9:52
  • 1
    unless you keep any ether or token balances in the contract, It can be. I would recommend to read this docs.openzeppelin.com/contracts/2.x/access-control. by setting access control u can avoid that. Commented Dec 25, 2022 at 10:52

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.