2. Creating a BMC Smart Contract

In this section we will be creating the smart contract that houses the BMC functionality. To get started, navigate to your contracts folder, create a new file named BuyMeACoffee.sol and paste this code below:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract BuyMeACoffee {
    // event to emit when a message is sent with tip
    event NewCoffee(address indexed _sender, string name, string _message, uint256 _timestamp);

    // address of contract deployer
    address payable owner;
    constructor() {
        // stores deployer as owner
        owner = payable(msg.sender);

    // struct of BuyMeACoffe Tx
    struct BuyCoffee {
        address sender;
        string name;
        uint timestamp;
        string message;

    // maps id to BuyCoffee struct
    mapping (uint => BuyCoffee) idToBuyCoffee;

    // id 
    uint public coffeeId;

    // buy coffee function
    function buyCoffee(string memory name, string memory message) public payable {
      // Must accept more than 0 KLAY for a coffee.
        require(msg.value > 0, "Tip must be greater than zero");

    // Add the coffee tx to storage
        BuyCoffee storage coffee = idToBuyCoffee[coffeeId];
        coffee.message = message;
        coffee.name = name;
        coffee.sender = msg.sender;
        coffee.timestamp = block.timestamp;
         // Emit a NewCoffee event with details about the coffee tx.
        emit NewCoffee(msg.sender, name, message, block.timestamp);

    // withdraw coffee tips to the contract owner
    function withdrawCoffeTips() public {
        require(_owner == msg.sender, "Not owner");
        require(owner.send(address(this).balance) );

     // get all coffee
    function getAllCoffee(uint _id) public view returns(BuyCoffee[] memory c){
        require(_id <= coffeeId, "Non-existent id");
        c = new BuyCoffee[](_id);
        for(uint i = 0; i < _id; i++) {
            c[i] = idToBuyCoffee[i + 1];

Let's quickly go over what each line of code does:

The NewCoffee event is emitted when a buyCoffee function is executed. It logs out the address of the sender, the name of the sender, the message sent, and the timestamp.

Next is the owner variable, which represents the contract deployer. We then set the msg.sender to be the owner of the contract in our constructor.

The coffeeId was created to keep track of the coffee transaction created.

Subsequently we declared a buyMeACoffee struct, which stores all the data related to a coffee transaction; address sender, string name, uint timestamp, string message. We then mapped this struct to an id using the idToBuyCoffee variable.

The buyCoffee function is the core implementation of BMC smart contract. It is a payable function which takes in two parameters, the name and address of the sender. It checks if the KLAY amount sent in is greater than zero. Next it increments the coffeeId, then it adds the coffee tx or info to the blockchain. Finally it emits a NewCoffee event, which entails the details of the coffee tx.

We created a withdraw() function to withdraw the total balance of the contract (address(this).balance) to the owner.

Finally, a getAllCoffee() function was created. It returns all the coffee transactions created overtime.

Now that we have completed writing our BMC smart contract, the next step is to test the functionalities of our smart contract, deploy and interact with the smart contract on Klaytn Testnet Baobab.

Last updated