Smart Contract
This smart contract is going to be used to tokenize the energy assets from green energy producers.
Green Energy Token
//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?