Token sale contract by ethers

I am trying to make a token sale contract for Ethers. But I have problems with the buy function. I think I have the problem with decimals, but I am not clear about it. I can’t get the equivalence right and it always gives me an error. Where am I going wrong?

I do not know if the price I put is in weis or not. Or even if it should actually divide rather than multiply the price.

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



interface TokenInterface {
    // determinamos las funciones que necesitamos del ERC20. Tienen que ser iguales.
    function decimals() external view  returns(uint8);
    function balanceOf(address _address) external view returns(uint256);
    function transfer(address _to, uint256 _value) external returns (bool success);
}


contract TokenSale  {
    address owner;
    uint256 price;
    TokenInterface TokenContract; // Variable de la interface.
    uint256 public tokensSold; // Acumulativo de tokens vendidos.
    
    event Sold(address indexed buyer, uint256 amount);
    
    modifier onlyOwner() {
         require(msg.sender == owner, "Solo puede llamar el propietario");
        _;
    }
    
    constructor(uint256 _price, address _addressContract) public {
        
        owner = msg.sender;
        price = _price;
        
        // pásamos el contrato del token a nuestra variable interface
        TokenContract = TokenInterface(_addressContract);
    }
    
    
  //No importamos toda la libreria SafeMath porque solamente necesitamos la función multiplicación.
  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    assert(c / a == b);
    return c;
  }
  
    function priceinWeis() public view  returns (uint256) {
    return price;
  }
  
 
    function setPrice(uint256 _newprice) public onlyOwner() {
    price = _newprice;
  }
  
  
   function etherBalance() public view onlyOwner() returns (uint256)  {
    return address(this).balance;
  }
  
   function tokenBalance() public view onlyOwner() returns (uint256)  {
    return TokenContract.balanceOf(address(this));
  }
  

   
  
    
  function buy(uint256 tokens) public payable {
        
        // que la cantidad que nos paga sea igual al precio x la cantidad de tokens que desea
        require(msg.value == mul(price, tokens)); 
        
        // al llamar la funcion original de transferencia tenemos que indicar la cantidad con los ceros de los decimales.
        uint256 amountwithzeros = mul(tokens, uint256(10) ** TokenContract.decimals());
        
        // comprobamos que el contrato de venta tenga los tokens que se desean comprar.
        require(TokenContract.balanceOf(address(this)) >= amountwithzeros); //address(this) direccion de nuestro contrato
        
        // realizamos la transferencia con un require por mayor seguridad.
        require(TokenContract.transfer(msg.sender, amountwithzeros)); // introducimos la cantidad escalada.
        
         // sumamos la venta.
        tokensSold += tokens; // fíjese, que usamos la cantidad sin la suma de los ceros de los decimales.
        
        emit Sold(msg.sender, tokens);
        
    }
    
    
    // Funcion que liquida el contrato para que no se pueda vender mas.
    function endSold() public  onlyOwner() {
        
        // compensacion de saldos. 
        require(TokenContract.transfer(owner, TokenContract.balanceOf(address(this))));
        msg.sender.transfer(address(this).balance);
       
    }
    

}

The code looks like ok, so if you want to make a successful transaction, you should meet all requirements of the function buy(),.

1). For this line:

require(msg.value == mul(price, tokens)); 

if current price is 10**18, and you want to buy 1 token, so you should pass 1 ether when you call this function to buy token.

2). For this line:

require(TokenContract.balanceOf(address(this)) >= amountwithzeros);

If you want to buy 1 token, the contract should at least have 1 token.

3).For this line:

require(TokenContract.transfer(msg.sender, amountwithzeros));

Expect to transfer toke to the caller successfully, but you should notice that TokenContract should be a standard ERC20 token, that is the function approve in the TokenContract should have a return value.

So if you meet three requirements above, your transaction will succeed.

First of all, thank you for your response.

  1. The price will be in weis. not? If I want to buy 100.000.000 of tokens, for example, it costs 1 ether. not the other way around. It makes no sense to sell tokens more expensive than an ether. This is where I get messed up because the price of a token would have to be the fraction, 0.00000001 not?

  2. Yes, before starting the sale, tokens will be sent to the sale contract by the token contract.

  3. Yes, the contract is a Standard erc20. this is my approve function in the contract:token:

function _approve(address owner, address spender, uint256 amount) internal {
    require(owner != address(0), "ERC20: approve from the zero address");
    require(spender != address(0), "ERC20: approve to the zero address");

    _allowances[owner][spender] = amount;
    emit Approval(owner, spender, amount);
  }

But, I dont use this function por transfer. I only use this function to addLiquidity

function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
    // approve token transfer to cover all possible scenarios
    _approve(address(this), address(uniswapV2Router), tokenAmount);

    // add the liquidity
    uniswapV2Router.addLiquidityETH{value: ethAmount}(
      address(this),
      tokenAmount,
      0, // slippage is unavoidable
      0, // slippage is unavoidable
      owner(),
      block.timestamp
    );
  }

But if the owner of the token contract and the sale contract is the same, why do I have to approve it? Or is it the address you want to buy that needs to be approved?

I would have to add this instruction before the transfer, right?

When I send the tokens to the sales contract, I verify that I must place the decimals. Here’s 1 ** 17 this doesn’t get a token, right?


If I have a price of 1000000 weis, and I want to sell 1000000 tokens, I would have to send this, right ?:
imagen1
1000000000000:
imagen2
It doesn’t work for me. I suspect that I actually have to add the 18 zeros when I send the tokens. But remix doesn’t allow me to put in so many zeros.

I think if you just want to use 1 eth to buy 100,000,000 token, so the current price should be

msg.value == mul(price, tokens)  => price=10**18/100000000=10**10

Great!

Yeah, if it is a standard ERC20 token, the function approve() will have a return value.

And in your showing code addLiquidity(), I think it will call transferFrom(). If you want to add liquidity by this contract, so there should be another function to do aprove, such as

function YOUR_APPROVE() public {
    token.aprove(router_address, amount);
}

so once you call this function YOUR_APPROVE(), your contract has approve the router contract, so now you can call the function to add liquidity.

I think this depends on the decimals of your token, eg: if the decimals of your token is 6, so 1*10**6 means 1 token, 1 means 0.000001 token.

On Sunday I managed to make the first test sale !! But I have to understand well everything that you point out to me here. But now I have another problem and I can't work on remix ... ... until I fix it, I won't be able to move on.

But thank you so much for all your time.

You can try using it. I wish you good work.

1 Like

Thanks @Xuser ,
I have discovered that it is a problem with the Brave browser.

I think I am wrong in the form. Theirs would be for the user to enter the ethers and the contract to calculate the amount of tokens he has to give.

With the pertinent security so that nobody pays more than one ether.

amount = msg.value * price and a condicional > 1 ether denegated.
not?

So have you deployed the contract on a testnet? Please share the contract address

He deployed a few for testing. Now I am testing that the purchase is automatically calculated based on the paid weis. That there is a purchase limit for one ether. Yesterday’s tests didn’t work for me. I will display the contracts today so you can observe it … in the meantime, I will show you the purchase function if you already see a problem in its design.

function buy() public payable {
      
      require( mul(msg.value, price) <= 1000000000000000000); 
        
        // calculo de los tokens que se van a mandar.
        uint256 tokens = mul(msg.value, price);
        
        // al llamar la funcion original de transferencia tenemos que indicar la cantidad con los ceros de los decimales.
        uint256 amountwithzeros = mul(tokens, uint256(10) ** TokenContract.decimals());
        
        // comprobamos que el contrato de venta tenga los tokens que se desean comprar.
        require(TokenContract.balanceOf(address(this)) >= amountwithzeros); //address(this) direccion de nuestro contrato
        
        // realizamos la transferencia con un require por mayor seguridad.
        require(TokenContract.transfer(msg.sender, amountwithzeros)); // introducimos la cantidad escalada.
        
         // sumamos la venta.
        tokensSold += tokens; // fíjese, que usamos la cantidad sin la suma de los ceros de los decimales.
        
        emit Sold(msg.sender, tokens);
        
    }

@Skyge As they say in my country, “what is promised is debt.” Here is the sale contract and the token contract on testnet.

Tokensale:
0xe836aA4610d4366636a5cB01707854ed6476E742 Rinkeby testnet

Token:
0x5627C82B74A98AD1D41C5522841570cD11fCB25B Same testnet.

No works.

I have set the security amount parameter, but the same problem occurs. I’m doing something wrong.