// SPDX-License-Identifier: MIT pragma solidity 0.8.36; contract HarmonyONEToken { string public constant name = "Harmony"; string public constant symbol = "ONE"; uint8 public constant decimals = 18; // 12.6 billion tokens at 2019 launch; at Year 2050: 12.6 + 0.441 * 31 = 26.271 B (in 18 decimals). uint256 public constant totalSupply = 26_271_000_000_000_000_000_000_000_000; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); error ERC20InvalidSender(address sender); error ERC20InvalidReceiver(address receiver); error ERC20InvalidApprover(address approver); error ERC20InvalidSpender(address spender); constructor(address recipient_) { if (recipient_ == address(0)) revert ERC20InvalidReceiver(address(0)); balanceOf[recipient_] = totalSupply; emit Transfer(address(0), recipient_, totalSupply); } function transfer(address to, uint256 value) external returns (bool) { _transfer(msg.sender, to, value); return true; } function approve(address spender, uint256 value) external returns (bool) { _approve(msg.sender, spender, value, true); return true; } function transferFrom(address from, address to, uint256 value) external returns (bool) { uint256 currentAllowance = allowance[from][msg.sender]; if (currentAllowance != type(uint256).max) { if (currentAllowance < value) revert ERC20InsufficientAllowance(msg.sender, currentAllowance, value); unchecked { _approve(from, msg.sender, currentAllowance - value, false); } } _transfer(from, to, value); return true; } function _transfer(address from, address to, uint256 value) private { if (from == address(0)) revert ERC20InvalidSender(address(0)); if (to == address(0)) revert ERC20InvalidReceiver(address(0)); uint256 fromBalance = balanceOf[from]; if (fromBalance < value) revert ERC20InsufficientBalance(from, fromBalance, value); unchecked { balanceOf[from] = fromBalance - value; } balanceOf[to] += value; emit Transfer(from, to, value); } function _approve(address owner, address spender, uint256 value, bool emitEvent) private { if (owner == address(0)) revert ERC20InvalidApprover(address(0)); if (spender == address(0)) revert ERC20InvalidSpender(address(0)); allowance[owner][spender] = value; if (emitEvent) emit Approval(owner, spender, value); } }