BEP20 Crowdsale

Hi everyone,
I am working on a crowdsale project for my first freelance client.
The budget is very small(Im trying to build a portfolio) so I cannot do mistakes due to deployment fees.
I have those two contracts:
Sales contract:

pragma solidity ^0.5.0;

import "./Crowdcoin.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/crowdsale/Crowdsale.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/crowdsale/emission/MintedCrowdsale.sol";

// @TODO: Inherit the crowdsale contracts
contract CrowdcoinSale is Crowdsale, MintedCrowdsale {

    constructor(
        // @TODO: Fill in the constructor parameters!
        uint rate, // rate in TKNbits
        address payable wallet, // sale beneficiary
        Crowdcoin token, // the Crowdcoin itself that the CrowdcoinSale will work with

    )
        // @TODO: Pass the constructor parameters to the crowdsale contracts.
        Crowdsale(rate, wallet, token)
        MintedCrowdsale()
        public

    {
        // constructor can stay empty
    }
}

contract CrowdcoinSaleDeployer {

    address public token_sale_address;
    address public token_address;

    constructor(
        // @TODO: Fill in the constructor parameters!
        string memory name,
        string memory symbol,
        address payable wallet // this address will receive all Ether raised by the sale

    )
        public
    {
        // @TODO: create the Crowdcoin and keep its address handy
        Crowdcoin token = new Crowdcoin(name, symbol, 0);
        token_address = address(token);


        // @TODO: create the CrowdcoinSale and tell it about the token, set the goal, and set the open and close times to now and now + 24 weeks.
        uint goal = 300 wei;
        uint cap = 300 wei;
        
        
        CrowdcoinSale Crowdcoin_sale = new CrowdcoinSale(1, wallet, token, goal, cap, now, now + 24 weeks);
        token_sale_address = address(Crowdcoin_sale);


        // make the CrowdcoinSale contract a minter, then have the CrowdcoinSaleDeployer renounce its minter role
        token.addMinter(token_sale_address);
        token.renounceMinter();
    }
}
``
Presale Token contract:
``
pragma solidity ^0.5.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20Mintable.sol";

contract crowdcoin is ERC20, ERC20Detailed, ERC20Mintable {
    constructor(
        string memory name,
        string memory symbol,
        uint initial_supply
    )
        ERC20Detailed(name, symbol, 18)
        public
    {
        mint(msg.sender, initial_supply);
    }
}

I plan to proceed like this:
1- Paste the crowdsale contract on remix.ethereum.org in the crowdsale.sol file that I will deploy with bsc
2- Paste the token on remix.ethereum.org in the crowdcoin.sol file that I will deploy with bsc
For the prior two steps, will they automatically work together?
how do I link it on my client’s website so the participants can connect their bnb wallets swap directly from the sale webpage?
Thank You in advance !

Hey can you tell us about the requirements of the crowdsale? Which features/function must it have?

I think so, pass crowdcoin as the value for Crowdcoin in the CrowdcoinSale, then CrowdcoinSale can work with crowdcoin.

This question is about the front-end, you can use metamsk or wallet connect to connect users’ wallet, just check the documentation of these plugins.

The crowdsale is just a mintable crowdsale, whereas for every purchase, new tokens are minted and sent to the buyer upon bnb receival at the defined rate. then the user must have a connect wallet button for metamask or trust wallet…
After they collect their wallet they must be able to see their bnb balance on the screen.

Thanks you for the reply so you mean I can edit crowdsale in that way:

constructor(
        // @TODO: Fill in the constructor parameters!
        uint rate, // rate in TKNbits
        address payable wallet, // sale beneficiary
        Crowdcoin crowdcoin, // the Crowdcoin itself that the CrowdcoinSale will work with

    )

or

@TODO: Pass the constructor parameters to the crowdsale contracts.
        Crowdsale(rate, wallet, crowdcoin? Or Deployed crowdcoin address)
        MintedCrowdsale()
        public

Or I need to deploy the crowdcoin contract first then use the contract address?
Thanks in advance !

Yeah, you should deploy crowdcoin at first, and then you can pass this address to the CrowdcoinSale

Well received thanks a lot
Is there anything about permissions?

I have used a very similar setup, You didn’t get inspired by the PupperCoin contract by any chance? My issue with this was that once the PupperCoinSaleDeployer has depoed the PupperCoinSale contract , you don’t really have any control over the token any more.

That might now be an issue for you though. I wanted to have extra minterrole for myself as well as the ability to burn tokens.

This is what I used then at least (Note that it’s old OpenZeppelin (V 2.5.1)

PupperCoin

// SPDX-License-Identifier: MIT

pragma solidity ^0.5.0;

import "https://github.com/Creepybits/openzeppelin/blob/main/contracts/token/ERC20/ERC20.sol";
import "https://github.com/Creepybits/openzeppelin/blob/main/contracts/token/ERC20/ERC20Detailed.sol";
import "https://github.com/Creepybits/openzeppelin/blob/main/contracts/token/ERC20/ERC20Mintable.sol";

contract PupperCoin is ERC20, ERC20Detailed, ERC20Mintable {
    constructor(
        string memory _name,
        string memory _symbo,
        uint initial_supply
    )
        ERC20Detailed(name, symbol, decimals)
        public
    {
        // constructor can stay empty
    }
}

PupperCoinCrowdSale

// SPDX-License-Identifier: MIT

pragma solidity ^0.5.0;

import "https://github.com/Creepybits/Puppercoin/blob/main/PupperCoin.sol";
import "https://github.com/Creepybits/openzeppelin/blob/main/contracts/crowdsale/Crowdsale.sol";
import "https://github.com/Creepybits/openzeppelin/blob/main/contracts/crowdsale/emission/MintedCrowdsale.sol";


// Inherit the crowdsale contracts:
contract PupperCoinCrowdsale is Crowdsale, MintedCrowdsale{

    constructor(
        // Constructor parameters:
        uint rate,
        address payable wallet,
        SvenskTiger token,
        uint goal,
        uint open,
        uint close
    )
        // Pass constructor parameters to the crowdsale contracts:
        Crowdsale(rate, wallet, token)
        public
    {
        // constructor can stay empty
    }
}

contract PuppercoinSaleDeployer {

    address public token_sale_address;
    address public token_address;

    constructor(
        // Constructor parameters:
        string memory name,
        string memory symbol,
        address payable wallet,
        uint goal
    )
        public
    {
        // Create the Puppercoin and keep its address:
        PupperCoin token = new PupperCoin(name, symbol, decimals);
        token_address = address(token);

        // Create the PupperCoinSale and tell it about the token, set the goal, and set the open and close times to now and (now + 24 weeks):
        PupperCoinSale token_sale = new PupperCoinSale(1, wallet, token, goal, now, now + 24 weeks);
        token_sale_address = address(token_sale);

        // Make the PupperCoinSale contract a minter, then have the PupperCoinSaleDeployer renounce its minter role:
        token.addMinter(token_sale_address);
        token.renounceMinter();
    }
}

If you want or need more control over the token and it’s sale, you might wan’t to consider other options.

1 Like