Smart Contract

This smart contract is going to be used to tokenize the energy assets from green energy producers.

Green Energy Token

GreenEnergyToken.sol
//SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;

import "./StandardERC20.sol";

/// @title Green Energy Token Contract
/// @author BlockExplorers
/// @notice This token is used in tokenize the energy assest from green energy producer
/// @dev Implements the ERC20 Contract
contract GreenEnergyToken is StandardERC20{

    /// @notice Stores the current state of carbon emissions from a company
    /// @dev State varible to track the company's footprint
    mapping(address => uint) footprintGenerated;
    
    /// @notice Store the approved IOT devices of a company
    /// @dev State varible to track the company's iot address
    mapping(address=>address) approvedIot;
    
    /// @notice State variable for address of contract owner
    /// @dev address of the contract owner
    /// @return Address of the contract owner
    address public owner;
    
    /// @notice Constructor of contract
    /// @dev used to initilaze the Token metadata and Inital supply
    constructor() StandardERC20("Green Energy Token", "GET", 100000000000000000000){
        owner = msg.sender;
    }

    /// @notice Modifier used to restrict the permission to the owner of the contract.
    /// @dev restricts the funtionality to owner
    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }
    /// @notice Modifier used to restrict the permission to the owner of the contract.
    /// @dev restricts the functionality to IOT address
    /// @param company address of the buyer
    modifier onlyIOT(address company){
        require(msg.sender == approvedIot[company]);
        _;
    }

    /// @notice To generate Event for Buy Action
    /// @dev Buy Event defiinition
    /// @param to address of the buyer
    /// @param amount amount of tokens requested to be bought
    event Buy(address indexed to, uint indexed footPrint, uint indexed amount);

    /// @notice To generate Event for Compensate Action
    /// @dev Compensate Event defiinition
    /// @param to address of the Token holder(company)
    /// @param amount amount of tokens requested to be compensated
    event Compensate(address indexed to, uint indexed footPrint, uint indexed amount);

    /// @notice Create new tokens and store it in smart contract
    /// @dev calls the _mint function from standard ERC20
    /// @param amount specifies the amount of token to be newly minted
    function mint(uint amount) public onlyOwner{
        _mint(address(this), amount);
    }

    /// @notice Function to add the footprint generated by company to the contract state
    /// @param company address of the company 
    /// @param footprint units of footprint generated by the company 
    function addFootprint(address company,uint footprint) public onlyIOT(company){
        footprintGenerated[company] += footprint;
    }
    
    /// @notice Obtain the total footprint of the company
    /// @dev utility function to access the state of the company
    /// @param company address of the company
    /// @return returns the total units of footprint generated by the company
    function getFootPrint(address company) public view returns(uint){
        return footprintGenerated[company];
    }

    /// @notice Facilitate the user to buy tokens
    /// @dev uses StandardERC20 _transfer function
    /// @param amount amount of tokens to be bought by the user
    function buy(uint amount)public payable{
        require(msg.value == amount);
        _transfer(address(this), msg.sender,amount);
        emit Buy(msg.sender,footprintGenerated[msg.sender],amount);
    }

    /// @notice Retrieve the address of the IOT Device of a company
    /// @dev Returns the address of the IOT dec
    /// @param company address of the company
    /// @return address of the IOT device approved by the company
    function getIOT(address company) public view returns(address){
        return approvedIot[company];
    }

    /// @notice Facilitate the user to compensate for the generated footprints
    /// @dev burns the specified amount of tokens
    /// @param amount amount of tokens the company wants to compensate
    function compensate(uint amount) public{        
        require(balanceOf(msg.sender)>= amount);
        _burn(msg.sender,amount);
        footprintGenerated[msg.sender] -=amount;
        emit Compensate(msg.sender,amount, amount);
    }

    /// @notice Approve an IOT device for the company
    /// @dev Should be executed before adding footprint
    /// @param spender address of the IOT device
    function approveIot(address spender) public{
        bool isApproved = approve(spender,getFootPrint(msg.sender));
        if(isApproved)
            approvedIot[msg.sender]=spender;
    }
    
    /// @notice Change the ownership of contract
    /// @dev Function to change the owner of the contract
    /// @param newOwner address of the new owner
    function changeOwner(address newOwner) public returns(bool){
        require(owner == msg.sender);
        owner = newOwner;
        return true;
    }
}

StandardERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract StandardERC20 is IERC20 {
    // state variables
    mapping (address => uint256) private _balances;
    
    mapping (address => mapping (address => uint256)) private _allowances;
    
    uint256 private _totalSupply;
    
    string private _name;
    string private _symbol;
    uint8 private _decimals;
    
    constructor (string memory name_, string memory symbol_, uint256 totalSupply_)  {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18; // 1 ether  = 10^18 wei
        _totalSupply = totalSupply_;
        _balances[msg.sender] = _balances[msg.sender] + totalSupply_;
        emit Transfer(address(0),msg.sender,_totalSupply);
    }
    
    function name() public view returns (string memory) {
        return _name;
    }
    
    function symbol() public view  returns (string memory){
        return _symbol;
    }
    
    function decimals() public view returns(uint8) {
        return _decimals;
    }
    
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }
    
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }
    
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(msg.sender, recipient,amount );
        return true;
    }
    
    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }
    
    function allowance(address owner, address spender) public override view returns(uint256) {
        return _allowances[owner][spender];
    } 
    
    function transferFrom(address sender, address recipient, uint256 amount) public override returns(bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender] - amount);
        return true;
    }
    
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(recipient != address(0),"ERC20: transfer from zero transfer");
        require(sender != address(0),"ERC20: transfer from zero transfer");
        
        _balances[sender] = _balances[sender] - amount;
        _balances[recipient] = _balances[recipient] + amount;
        emit Transfer(sender, recipient, amount);
    }
    
    function _approve(address owner, address spender, uint256 amount) internal {
        require(spender != address(0),"ERC20: transfer from zero transfer");
        require(owner != address(0),"ERC20: transfer from zero transfer");
        require(_balances[owner] >= amount, "ERC20: owner does not have enough amount");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] = accountBalance - amount;
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);
    }
    
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

Last updated

Was this helpful?