Skip to main content

1. Deploy SOL Contract (SDK)

For this contract example we're using OpenZepellin interfaces and the Hedera Solidity Libraries for HTS.

Spend some time looking into both links there is a lot of interesting documentation to help you create bullet-proof contracts!

1.1 About the Contract

The contract will handling minting a token, receiving hbar payments, and keeping a ledger of people that make donations. When donations hit 90%, the contract admin can release the donations of hbar.

Screenshot

Sample of our contract code below

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.6.0 <0.9.0; import './hedera.contracts/token.service/HederaResponseCodes.sol';import './hedera.contracts/token.service/IHederaTokenService.sol';import './hedera.contracts/token.service/HederaTokenService.sol';import './hedera.contracts/token.service/ExpiryHelper.sol'; import './oz.contracts/token/ERC20/IERC20.sol';import './oz.contracts/token/ERC20/extensions/IERC20Metadata.sol'; contract FairTradeCoffee is ExpiryHelper {    receive() external payable {}    fallback() external payable {}    event FairTradeEvent(        address indexed from,        uint256 timestamp,        string name,        string message    );        // Memo struct.    struct FairTradeBuyer {        address from;        uint256 timestamp;        string name;        string message;        uint256 amount;    }    struct FairTradeMetadata {        string creatorName;        string tokenSymbol;        string tokenName;        uint256 tokenSupply;        address tokenAddress;    }        address payable owner;    FairTradeBuyer[] fairTradeBuyers;    FairTradeMetadata fairTradeMetadata;    constructor(string memory _creatorName, string memory _tokenSymbol, string memory _tokenName, uint256 _tokenSupply) {        owner = payable(msg.sender);        fairTradeMetadata.creatorName = _creatorName;        fairTradeMetadata.tokenSymbol = _tokenSymbol;        fairTradeMetadata.tokenName = _tokenName;        fairTradeMetadata.tokenSupply = _tokenSupply;    }    function getContractBalance() public view returns (uint) {        return address(this).balance;    }    function getTokenRemainingBalance() public view returns (uint) {        return fairTradeMetadata.tokenSupply;    }    function makeDonationHbars(string memory _name, string memory _message, uint256 _amount) external payable returns (uint)  {        require(_amount > 0, "Please send some hbars :)");        if (fairTradeMetadata.tokenSupply < _amount) {            revert ("Transfer Failed. Not enough tokens to go around");        }         fairTradeBuyers.push(FairTradeBuyer(            msg.sender,            block.timestamp,            _name,            _message,            _amount        ));        fairTradeMetadata.tokenSupply -= _amount;        return msg.value;    }    function withdrawDonations() public {        require(fairTradeMetadata.tokenSupply <= 10000, "Not yet, we need more donations!");        require(owner.send(address(this).balance));    }    function getFairTradeBuyerNumbers() public view returns (uint) {        return fairTradeBuyers.length;    }    function getFairTradeBuyers() public view returns (FairTradeBuyer[] memory) {        return fairTradeBuyers;    }    function getContractMetadata() public view returns (FairTradeMetadata memory) {        return fairTradeMetadata;    }    function mintFungibleToken() external payable returns (address createdTokenAddress) {        require(fairTradeMetadata.tokenAddress == address(0));        uint decimals = 0;        uint32 autoRenewPeriod = 7000000;             IHederaTokenService.HederaToken memory token;        token.name = fairTradeMetadata.tokenName;        token.symbol = fairTradeMetadata.tokenSymbol;        token.treasury = address(this);        token.expiry = createAutoRenewExpiry(address(this), autoRenewPeriod);                // call HTS precompiled contract, passing initial supply and decimals        (int _responseCode, address _tokenAddress) = HederaTokenService.createFungibleToken(token, fairTradeMetadata.tokenSupply, decimals);         if (_responseCode != HederaResponseCodes.SUCCESS) {           revert ();        }         createdTokenAddress = _tokenAddress;        fairTradeMetadata.tokenAddress = createdTokenAddress;    }}

1.2 Compile Contract

Navigate to Arkhia quick-start contracts section and run the command below (make sure you have solcjs installed)

solcjs --bin --abi -o build fairtrade.token.sender.sol

This will generate under the build folder

1. ```bin``` file to deploy the contract
2. ```ABI``` for frontend integration

1.3 Deploy Contract to Hedera

info

For this example we're using the SDK , although you can also use Truffle/Hardhat. We will come out with examples using those frameworks in the future.

Open contracts/1.1.deploy.contract.js

Under the method main look for any variables you would like to change. Here we define the token as well the path to the contract bin.

 // Set variables    const client = await clientHandler.getTestnetClient();    const treasuryKey = await clientHandler.getTestnetPrivateKey();    // Set variables    const tokenInfo = { creatorName: "Arkhia3", tokenSymbol: "AFTC3", tokenName: "ArkhiaFairTrade3", initialSupply: 100000 };        // 1. Deploy Contract    const getFairTradeContractPath = './../../../../contracts/build/fairtrade_token_sender_sol_FairTradeCoffee.bin';    const result = await CreateFairTradeCoffeeInitialData(getFairTradeContractPath, tokenInfo, client, treasuryKey);    console.log(`Final Output successfull`);    console.log(result);    console.log(`\n Please verify all the elements were created successfully.\n\n`);    console.log(`Contract:          https://explorer.arkhia.io/#/testnet/contract/${result.contractId}`);    console.log(`Contract Token:    https://explorer.arkhia.io/#/testnet/token/${result.fungibleTokenId}`);

Run the command below from the terminal

node 1.1.deploy.contract.js

1.4 Verify Output

The console output should be similar to this

Screenshot

1.5 Is this thing running?

Open contracts/1.2.sanity.check.contract.js

    async function main() {        // Init clients/users        const client = await clientHandler.getTestnetClient();        // 1. Sanity Check        const contractId = `0.0.49226471`; // example        await tokenContractSanityCheck(client, contractId, "Arkhia", "Is this thing running", 50);            // 2. Withdraw donations (should fail)        // await getDonations(client, result.contractId)}

Run the command below from the terminal

node 1.2.sanity.check.contract.js

1.6 Verify Output

The console output should be similar to this

Screenshot

What happened?

  1. We build the necessary Bin and ABI files
  1. FairTrade contract deployed on Hedera using the Bin file generate earlier
  1. Call the Mint method in the contract to mint the fungible token associated with the contract
  1. Make a donation to check Contract receives hbar balance Token supply changes Fair trade buyers is held by the contract
info

As of the date of this tutorial, calls to fetch data from EVM contracts on Hedera cost small amounts of HBAR.