1

Here is my solidity

interface IERC20 {
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}

interface V2 {
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}

pragma solidity ^0.5.17;
contract tokenSales {
    //string public name = "EthSwap Instant Exchange";
    
    // IERC20 public token;
    // V2 public rgp;
    address token = 0x87e9D87f85e80D79A77067A090F0748241892F74;
    address rgp = 0x153Eef8365e8F4ae62aC99b6C84520f81F572827;
    address owner;
    uint public price;
    
    uint256 public tokensSold;
    uint256 public decimals;
    
    event sold(address account, uint price, address token);
    
    modifier onlyOwner() {
        require(
            msg.sender == owner,
            "RGP Token: Caller is not the Owner"
        );
        _;
    }

    constructor(uint _price) public payable{
        owner ==  msg.sender;
        price = _price;
 
        // SMC: 0xDA0bab807633f07f013f94DD0E6A4F96F8742B53
    }
    
    function() external payable{
        buyTokens();
        msg.value;
    }

    // Guards against integer overflows
    function mul(uint x, uint y) public pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
    }
        
        //uint tokens = contribution.mul(multiplier).div(TOKEN_PRICE);
        //tokenAllocations[investor] = tokenAllocations[investor].add(tokens);
        //tokensSold = tokensSold.add(tokens);
    
    function setBUSDCPrice(uint _price) public onlyOwner {
        price = _price;
    }
    
    function sendCollectedBUSDC (address payable _recipient)
        external
        onlyOwner
    {
        if (address(this).balance > 0) {
            _recipient.transfer(address(this).balance);
        }
    }

    function buyTokens() public payable {
        //CHECK FOR INPUT BALLANCE
        require(msg.value > 0, "RGP: INSUFFICIENT INPUT BALLANCE, YOU NEED TO SEND SOME BUSDT");
        
        //CALCULATE THE AMOUNT OF TOKEN TO PURCHASE
        uint256 tokensToBuy = mul(msg.value, uint256(10) ** IERC20(token).decimals()) / mul(price, uint256(10) ** V2(rgp).decimals());
        
        //ALLOWANCE FOR BOTH ADDRESS(THIS) AND MSG.SENDER
        V2(rgp).allowance(msg.sender, address(this));
        IERC20(token).allowance(address(this), msg.sender);
        
        //REQUIREMENT FOR ALLOWANCE
        tokensToBuy <= V2(rgp).allowance(address(this), msg.sender); // "RGP: CHECK THE TOKEN ALLOWANCE OF ADMIN";
        msg.value <= IERC20(token).allowance(msg.sender, address(this)); // "RGP: CHECK THE TOKEN BALANCE OF BUYER";
        
        //APPROVE FOR BOTH MSG.SENDER AND ADDRESS(THIS)
        V2(rgp).approve(msg.sender, tokensToBuy);
        IERC20(token).approve(address(this), msg.value);
        
        //TRANSFER FROM MSG.SENDER TO ADDRESS(THIS)
        IERC20(token).transferFrom(msg.sender, address(this), msg.value);
        
        //CHECK FOR BALANCE OF ADMIN
        uint256 rgpBalance = V2(rgp).balanceOf(address(this));
        
        //REQUIRE THAT THE BALANCE APPROVED IS GREATER THAN THE TOKENS TO BUY.
        require(rgpBalance >= tokensToBuy, "RGP: NOT ENOUGH TOKEN IN THE RESERVE");
        
        //TRANSFER FROM RGP TO MSG.SENDER
        V2(rgp).transferFrom(address(this), msg.sender, tokensToBuy);
        
        //REDUCE THE ALLOWANCE OF BOTH PARTIES
        IERC20(token).allowance(msg.sender, address(this)) + msg.value;
        V2(rgp).allowance(address(this), msg.sender) + tokensToBuy;
        
        //INCREASE THE ALLOWANCE OF BOTH PARTIES.
        IERC20(token).allowance(msg.sender, address(this)) + msg.value;
        V2(rgp).allowance(address(this), msg.sender) + tokensToBuy;
       
        // 
        tokensSold += msg.value; 
        emit sold(msg.sender, msg.value * price, address(token));
        
    }

    function endSale() public onlyOwner{
            // Send unsold tokens to the owner.
        require(V2(rgp).transfer(owner, address(this).balance), "RGP: Sales ended.");
        require(IERC20(token).transfer(owner, address(this).balance), "RGP: Sales ended.");
    
        msg.sender.transfer(address(this).balance);
    }
}

Deployed to ropsten "HERE"

The token address "TOKEN ADDRESS".

Please I have been on this for some days trying to figure out what wrong but I couldn't I have checked related issues on this platform and others still the same, I actually taught it was stress so I decided to take some time out and came back still can't figure it out.

I test on remix it deducts ether from msg.sender and did not credit to smart contract address and as well msg.sender did not receive token.

12
  • I have intermediary knowledge of how it works, msg.sender approves the smart contract address to spent the _amount, and the smart contract transfer from msg.sender the _amount to its address and vice-verser, this was my taught please correct me if am wrong. i used on token because i want the smart contract to credit the msg.sender _amount * price.
    – Prosperity
    Commented Jan 3, 2021 at 18:06
  • This formula looks wrong _amount1 * 10 * decimals / _amount1 / price, mathematically is equivalent to 10 * decimals / price. Using approve+transferFrom doesn't work like you seems to be expecting. To accept ether payment you should use msg.amount. I'd suggest to read some tutorial or book.
    – Ismael
    Commented Jan 3, 2021 at 19:06
  • yea, thanks for your prompt response.
    – Prosperity
    Commented Jan 4, 2021 at 21:17
  • i used this "uint256 tokensToBuy = mul(msg.value, uint256(10) ** rgp.decimals());" but nothing seems to happened that y i tried it foolishly. trying to transfer from contract address back to msg.sender address using the transfer keyword and will get back.
    – Prosperity
    Commented Jan 4, 2021 at 21:18
  • 1
    @Ismael, really appreciate your support have been able to achieve that. And it set and up 'n' running.
    – Prosperity
    Commented Jan 15, 2021 at 2:44

1 Answer 1

1

well coming back to answer my own question, it great and lovely thou. my interface

interface IBEP20 {
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}

and the function that handles the buy tokens

// Note: This function allows only purchases of "full" tokens, purchases of 0.1 tokens or 1.1 tokens for example are not possible
    function buyTokens(uint256 _tokenAmount) public {
        
        // Check if sale is active and user tries to buy atleast 1 token
        require(saleActive == true, "TOK: SALE HAS ENDED.");
        require(_tokenAmount >= 1, "TOK: BUY ATLEAST 1 TOKEN.");
        
        // Calculate the purchase cost
        uint256 cost = _tokenAmount * price;
        
        // Calculate the tokens _msgSender() will get (with decimals)
        uint256 tokensToGet = _tokenAmount * 10**18;
        
        // Transfer busd from _msgSender() to the contract
        // If it returns false/didn't work, the
        //  msg.sender may not have allowed the contract to spend busd or
        //  msg.sender or the contract may be frozen or
        //  msg.sender may not have enough busd to cover the transfer.
        require(IBEP20(busd).transferFrom(_msgSender(), address(this), cost), "TOK: TRANSFER OF BUSD FAILED!");
        
        // Transfer TOK to msg.sender
        // If it returns false/didn't work, the contract doesn't own enough tokens to cover the transfer
        require(IBEP20(tok).transfer(_msgSender(), tokensToGet), "TOK: CONTRACT DOES NOT HAVE ENOUGH TOKENS.");
        
        tokensSold += tokensToGet;
        emit Sale(_msgSender(), price, tokensToGet);
    }

@Ismael thanks for your contribution thus far

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.