Search code examples
blockchainethereumsolidityerc20

How to allow to send tokens from an appropriate addresses only?


I've created the ERC20 contract, compiled it in Remix and deployed to Sepolia testnet. How can I make this contract to send tokens from an appropriate addresses only. Other addresses should not be allowed to send. Thanks in advance.

Here's the contract code:

pragma solidity ^0.4.24;
 
//Safe Math Interface
 
contract SafeMath {
 
    function safeAdd(uint a, uint b) public pure returns (uint c) {
        c = a + b;
        require(c >= a);
    }
 
    function safeSub(uint a, uint b) public pure returns (uint c) {
        require(b <= a);
        c = a - b;
    }
 
    function safeMul(uint a, uint b) public pure returns (uint c) {
        c = a * b;
        require(a == 0 || c / a == b);
    }
 
    function safeDiv(uint a, uint b) public pure returns (uint c) {
        require(b > 0);
        c = a / b;
    }
}
 
 
//ERC Token Standard #20 Interface
 
contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);
 
    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
 
 
//Contract function to receive approval and execute function in one call
 
contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}
 
//Actual token contract
 
contract Tether is ERC20Interface, SafeMath {
    string public symbol;
    string public  name;
    uint8 public decimals;
    uint public _totalSupply;
 
    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;
 
    constructor() public {
        symbol = "USDT";
        name = "Tether";
        decimals = 6;
        _totalSupply = 1000000000000000;
        balances[0xC6AE84c5275E47F9607254Bbc4937fCCbA72B3E5] = _totalSupply;
        emit Transfer(address(0), 0xC6AE84c5275E47F9607254Bbc4937fCCbA72B3E5, _totalSupply);
    }
 
    function totalSupply() public constant returns (uint) {
        return _totalSupply  - balances[address(0)];
    }
 
    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }
 
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }
 
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }
 
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(from, to, tokens);
        return true;
    }
 
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }
 
    function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
        return true;
    }
 
    function () public payable {
        revert();
    }
}

I tried to rewrite the approve function like this but it didn't work out. Tokens still can sent from any address.

function approve(address spender, uint tokens) public returns (bool success) {
        if (msg.sender == address(0x...)) {
            allowed[msg.sender][spender] = tokens;
            emit Approval(msg.sender, spender, tokens);
            return true;
        } else {
            allowed[msg.sender][spender] = 0;
            emit Approval(msg.sender, spender, 0);
            return false;
        }
    }

Solution

  • If you like to enable the transfer only for certain addresses, then you should instead add the if-else logic not in approve, but instead in transfer.

    So your code should look something like this.

    function transfer(address to, uint tokens) public returns (bool success) {
       if (msg.sender == "specific-address") {
          balances[msg.sender] = safeSub(balances[msg.sender], tokens);
          balances[to] = safeAdd(balances[to], tokens);
          emit Transfer(msg.sender, to, tokens);
          return true;
       }
    
       return false;
    }
    

    This way if other addresses try to transfer the token then it will fail to do so using transfer.