はじめに
初めまして。 CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です! スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。
代表的なゲームはクリプトスペルズというブロックチェーンゲームです。
今回はERC1155の拡張機能であるERC5615について解説していきます。
主に以下の記事をもとに解説していきます。
概要
ERC1155の拡張機能です。
ERC1155トークンに、与えられたトークンIDを持つトークンの数を取得するtotalSupply関数と、与えられたトークンIDの存在を確認するexists関数を追加します。
ERC1155nいついては以下の記事を参考にしてください。
仕様
ERC165インターフェースをサポートできるが、利用者はそれに依存してはならない。
interface ERC1155Supply is ERC1155 {
function exists(uint256 id) external view returns (bool);
function totalSupply(uint256 id) external view returns (uint256);
}exists
特定のトークンIDが「存在する」、「存在しない」、「存在する可能性がある」を返す関数。 「存在する可能性がある」とは、まだ発行されていないがトークンIDとしては存在する状態。
引数
id- トークンID。
戻り値
特定のトークンIDが「存在するか」、「存在したか」、「存在する可能性があるか」。
totalSupply
特定のトークンIDのトークン数を返す関数。 存在しないトークンIDを指定した場合は0を返す。
引数
id- トークンID。
戻り値
指定したトークンIDの総供給量。
補足
ERC165を実装していません。 理由としては、このインターフェースは十分にシンプルで、既存の実装との互換性を損なう可能性があるからです。
totalSupplyとexists関数は、ERC721とERC20を参考に作られました。
totalSupplyは、トークンIDが存在しない場合でもリバートしません。
なぜなら、存在の確認のためにはexistsを使用すべきだからです(totalSupplyが0であっても、falseを返す可能性があります)。
existsは、totalSupplyがゼロになる以下の2つを区別するために使用されます。
- 与えられたIDを持つトークンがまだ発行されていない。
- 与えられたIDを持つトークンが一切発行されない。
後方互換性
OpenZeppelinのERC1155Supplyとの後方互換性を持つように設計されています。
実装
Openzeppelinでの実装コードです。
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)
pragma solidity ^0.8.19;
import {ERC1155} from "../ERC1155.sol";
abstract contract ERC1155Supply is ERC1155 {
mapping(uint256 => uint256) private _totalSupply;
uint256 private _totalSupplyAll;
function totalSupply(uint256 id) public view virtual returns (uint256) {
return _totalSupply[id];
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupplyAll;
}
function exists(uint256 id) public view virtual returns (bool) {
return totalSupply(id) > 0;
}
/**
* @dev See {ERC1155-_update}.
*/
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal virtual override {
super._update(from, to, ids, values);
if (from == address(0)) {
uint256 totalMintValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply[ids[i]] += value;
totalMintValue += value;
}
// Overflow check required: The rest of the code assumes that totalSupplyAll never overflows
_totalSupplyAll += totalMintValue;
}
if (to == address(0)) {
uint256 totalBurnValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
unchecked {
// Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i])
_totalSupply[ids[i]] -= value;
// Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
totalBurnValue += value;
}
}
unchecked {
// Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
_totalSupplyAll -= totalBurnValue;
}
}
}
}最後に
今回の記事では、ERC5615について解説してきました。 いかがだったでしょうか?
実行については今後追記していきたいと思います!
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
採用強化中!
CryptoGamesでは一緒に働く仲間を大募集中です。
この記事で書いた自分の経験からもわかるように、裁量権を持って働くことができて一気に成長できる環境です。 「ブロックチェーンやWeb3、NFTに興味がある」、「スマートコントラクトの開発に携わりたい」など、少しでも興味を持っている方はまずはお話ししましょう!

