Skip to content

Instantly share code, notes, and snippets.

@darkerego
Created November 4, 2024 03:44
Show Gist options
  • Save darkerego/faf6972e61c10fa22bbb19af23ab9abc to your computer and use it in GitHub Desktop.
Save darkerego/faf6972e61c10fa22bbb19af23ab9abc to your computer and use it in GitHub Desktop.
A minimalist ERC20 token size optimized for low deployment costs.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
abstract contract MinimalistErc20 {
address public owner;
string public name;
string public symbol;
uint256 public totalSupply;
uint8 immutable public decimals;
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowances;
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed _account, address indexed spender, uint indexed amount);
/*
@dev custom error function are cheaper than require statements
*/
error InsufficientBalance(address, uint256);
error InsufficientAllowance(address, address, uint256);
error Unauthorized();
error UseBurn();
constructor(string memory _symbol, string memory _name){
symbol = _symbol;
name = _name;
decimals = 18;
owner = msg.sender;
}
function _transfer(address _from, address _to, uint256 _amount) internal returns(bool) {
if (_from == address(0) && _to != address(0)) {
// Mint tokens
totalSupply += _amount;
balanceOf[_to] += _amount;
emit Transfer(_from, _to, _amount);
return true;
}
else if (_to == address(0) && _from != address(0)) {
// Burn tokens
if (balanceOf[_from] < _amount) {
revert InsufficientBalance(_from, _amount);
}
totalSupply -= _amount;
balanceOf[_from] -= _amount;
emit Transfer(_from, _to, _amount);
return true;
}
else {
// Regular transfer
if (balanceOf[_from] < _amount) {
revert InsufficientBalance(_from, _amount);
}
balanceOf[_from] -= _amount;
balanceOf[_to] += _amount;
emit Transfer(_from, _to, _amount);
return true;
}
}
function burn(uint amount) external returns(bool) {
return _transfer(msg.sender, address(0), amount);
}
function mint(uint256 _amount, address _to) public returns(bool) {
if (msg.sender != owner) {
revert Unauthorized();
}
_transfer(address(0), _to, _amount);
return true;
}
function approve(address _spender, uint256 _amount) external returns(bool) {
allowances[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
return true;
}
function increaseAllowance(address _spender, uint256 addedValue) external returns(bool) {
allowances[msg.sender][_spender] += addedValue;
emit Approval(msg.sender, _spender, allowances[msg.sender][_spender]);
return true;
}
function decreaseAllowance(address _spender, uint256 subtractedValue) external returns(bool) {
uint256 currentAllowance = allowances[msg.sender][_spender];
if (subtractedValue > currentAllowance) {
revert InsufficientAllowance(msg.sender, _spender, subtractedValue);
}
allowances[msg.sender][_spender] -= subtractedValue;
emit Approval(msg.sender, _spender, allowances[msg.sender][_spender]);
return true;
}
function transfer(address to, uint256 amount) external returns(bool) {
if (to == address(0)) {
revert UseBurn();
}
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) external returns(bool) {
if (to == address(0)) {
revert UseBurn();
}
if (allowances[from][msg.sender] < amount) {
revert InsufficientAllowance(from, to, amount);
}
// Deduct the allowance
allowances[from][msg.sender] -= amount;
return _transfer(from, to, amount);
}
function renounceOwnership() external returns(bool) {
if (msg.sender == owner) {
owner = address(0);
return true;
} else {
revert Unauthorized();
}
}
}
contract TestToken is MinimalistErc20 {
constructor() MinimalistErc20("Test", "T") {
mint(1000000 * 10**decimals, msg.sender);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment