Skip to content

Instantly share code, notes, and snippets.

@z0r0z
Last active February 28, 2022 09:10
Show Gist options
  • Save z0r0z/9a1e292390a4441dfe13843c12d38dd8 to your computer and use it in GitHub Desktop.
Save z0r0z/9a1e292390a4441dfe13843c12d38dd8 to your computer and use it in GitHub Desktop.
what ERC-1155 could have been
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient MultiToken implementation adhering as closely to ERC20 interface.
/// @author Ross, modified from (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
abstract contract MultiToken {
/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 indexed id, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
/*///////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory);
/*///////////////////////////////////////////////////////////////
TOKEN STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => uint256) public totalSupplyForId;
mapping(address => mapping(uint256 => uint256)) public balanceOf;
mapping(address => mapping(address => mapping(uint256 => uint256))) public allowance;
/*///////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
/*///////////////////////////////////////////////////////////////
TOKEN LOGIC
//////////////////////////////////////////////////////////////*/
function approve(
address spender,
uint256 id,
uint256 amount
) public virtual {
allowance[msg.sender][spender][id] = amount;
emit Approval(msg.sender, spender, id, amount);
}
function transfer(
address to,
uint256 id,
uint256 amount
) public virtual {
balanceOf[msg.sender][id] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to][id] += amount;
}
emit Transfer(msg.sender, to, id, amount);
}
function transferFrom(
address from,
address to,
uint256 id,
uint256 amount
) public virtual {
uint256 allowed = allowance[from][msg.sender][id]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender][id] = allowed - amount;
balanceOf[from][id] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to][id] += amount;
}
emit Transfer(from, to, id, amount);
}
/*///////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(
address to,
uint256 id,
uint256 amount
) internal virtual {
totalSupplyForId[id] += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to][id] += amount;
}
emit Transfer(address(0), to, id, amount);
}
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
balanceOf[from][id] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupplyForId[id] -= amount;
}
emit Transfer(from, address(0), id, amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment