Utility Token
1 utility token for energy will be 1 W
StandardERC20 Token implementation
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/24a0bc23cfe3fbc76f8f2510b78af1e948ae6651/contracts/token/ERC20/IERC20.sol";
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;
_totalSupply = _totalSupply_;
_balances[msg.sender] = _balances[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");
require(_balances[sender] >= amount, "ERC20: sender does not have enough amount");
_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 _toAccount, uint256 _amount) public {
require(_toAccount != address(0), "ERC20: mint to the zero address");
require(_totalSupply + _amount >= _totalSupply,"overflow");
require(_balances[_toAccount] + _amount >= _balances[_toAccount],"overflow");
_totalSupply += _amount;
_balances[_toAccount] += _amount;
emit Transfer(address(0), _toAccount, _amount);
}
function burn(address _fromAccount, uint256 _amount) public {
require(_fromAccount != address(0), "ERC20: mint to the zero address");
require(_balances[_fromAccount] - _amount <= _balances[_fromAccount],"underflow");
require(_totalSupply - _amount <= _totalSupply,"underflow");
_totalSupply -= _amount;
_balances[_fromAccount] -= _amount;
emit Transfer(_fromAccount, address(0), _amount);
}
function increaseAllowance(address spender, uint256 addedValue) public returns(bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 addedValue) public returns(bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender] - addedValue);
return true;
}
}
Utility Token implementation
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./StandardERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/9425a7e0ab1d45c48845d47afc33856ad9d98b0c/contracts/access/Ownable.sol";
contract GreenToken is StandardERC20, Ownable {
mapping(address=>address) public meterToOwner; // Map address of meter to the meter owner wallet
mapping(address=>address[]) public ownerToMeter; // Map address of owner wallet to the meter
address[] public meters;
constructor () StandardERC20("Green","JOY",10000){
}
event Burn(address indexed burner, uint256 value); // Burn tokens based on power consumption from the meters wallet
event Mint(address indexed to, uint256 amount); // Mint tokens based on power production to the meters wallet
modifier hasMintPermission() { // Requires that only the meter address can call the mint function based on production
require(meterToOwner[msg.sender] != address(0) || msg.sender == owner());
_;
}
modifier onlyMeterOwner(address _meterAddress){
require(meterToOwner[_meterAddress] == msg.sender);
_;
}
function enrollMeter(address _meterAddress, address _ownerAddress) onlyOwner public {
meterToOwner[_meterAddress] = _ownerAddress; // Bind meter to owner
ownerToMeter[_ownerAddress].push(_meterAddress); // Bind owner to meter
meters.push(_meterAddress);
}
function transferMeterOwnership(address _meterAddress, address _newOwnerAddress) onlyMeterOwner(_meterAddress) public {
meterToOwner[_meterAddress] = _newOwnerAddress;
ownerToMeter[_newOwnerAddress].push(_meterAddress);
}
function burn(uint256 _value) public { // Burn tokens from the meter's own wallet [msg.sender]
super.burn(msg.sender, _value);
emit Burn(msg.sender,_value);
}
function mint(uint256 _amount) public hasMintPermission returns (bool) {
super.mint(msg.sender,_amount);
increaseAllowance(meterToOwner[msg.sender], _amount);
emit Mint(msg.sender, _amount);
return true;
}
function mintTo(uint256 _amount, address _recipient)public onlyOwner returns (bool){
increaseAllowance(meterToOwner[_recipient], _amount);
emit Mint(_recipient, _amount);
return true;
}
function getAllMeters() public view returns(address[] memory){
return meters;
}
function getAllMetersForOwner(address _owner)public view returns (address[] memory){
return ownerToMeter[_owner];
}
}