2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 代币标准--ERC1155协议源码解析

代币标准--ERC1155协议源码解析

时间:2021-06-10 09:36:48

相关推荐

代币标准--ERC1155协议源码解析

ERC1155多代币标准

ERC1155结合了ERC20和ERC721的能力,这是一个标准接口,支持开发同质化的、半同质化的、非同质化的代币和其他配置的通用智能合约。

IERC1155接口

// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)pragma solidity ^0.8.0;import "../../utils/introspection/IERC165.sol";// IERC1155接口同样继承了IERC165接口interface IERC1155 is IERC165 {

TransferSingle事件

// 转移代币后触发事件,记录转移信息event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

TransferBatch事件

// 批量转移代币后触发事件,记录转移信息event TransferBatch(address indexed operator,address indexed from,address indexed to,uint256[] ids,uint256[] values);

ApprovalForAll事件

// 授权approve后触发事件,记录授权信息event ApprovalForAll(address indexed account, address indexed operator, bool approved);

URI事件

// URI的值改变时触发该事件,记录信息event URI(string value, uint256 indexed id);

balanceOf函数

// 获取account账户对应代币id拥有的数量function balanceOf(address account, uint256 id) external view returns (uint256);

balanceOfBatch函数

// 获取账户列表对用的token余额,相当于多次balanceOffunction balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)externalviewreturns (uint256[] memory);

setApprovalForAll函数

// 设置给operate的授权function setApprovalForAll(address operator, bool approved) external;

isApprovedForAll函数

// 判断operate是否有account账号的授权function isApprovedForAll(address account, address operator) external view returns (bool);

safeTransferFrom函数

// 从from账户转移amount数量的代币id到to地址function safeTransferFrom(address from,address to,uint256 id,uint256 amount,bytes calldata data) external;

safeBatchTransferFrom函数

// 批量转移token,相当于调用多次safeTransferfunction safeBatchTransferFrom(address from,address to,uint256[] calldata ids,uint256[] calldata amounts,bytes calldata data) external;}

ERC1155

// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)pragma solidity ^0.8.0;import "./IERC1155.sol";import "./IERC1155Receiver.sol";import "./extensions/IERC1155MetadataURI.sol";import "../../utils/Address.sol";import "../../utils/Context.sol";import "../../utils/introspection/ERC165.sol";contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {using Address for address;

// 代币id与拥有者地址及其该代币余额的映射mapping(uint256 => mapping(address => uint256)) private _balances;

// 地址之间的授权状态的映射mapping(address => mapping(address => bool)) private _operatorApprovals;

// 相同类型的代币 _uri是一致的string private _uri;

// 构造函数 初始化uriconstructor(string memory uri_) {_setURI(uri_);}

supportsInterface函数

// 检查合约是否实现该接口function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {returninterfaceId == type(IERC1155).interfaceId ||interfaceId == type(IERC1155MetadataURI).interfaceId ||super.supportsInterface(interfaceId);}

uri函数

// 获取代币的uri,uri指向是代币的元数据,例如图片信息function uri(uint256) public view virtual override returns (string memory) {return _uri;}

balanceOf函数

// 获取account地址的id代币的数量function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {// 检查account不为空地址require(account != address(0), "ERC1155: address zero is not a valid owner");return _balances[id][account];}

balanceOfBatch函数

// 返回account账号列表对应的id代币的数量function balanceOfBatch(address[] memory accounts, uint256[] memory ids)publicviewvirtualoverridereturns (uint256[] memory){// 检查账号列表长度与代币id列表长度一致require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");// 创建一个列表长度与account相同uint256[] memory batchBalances = new uint256[](accounts.length);// 获取账号对应的代币id的数量for (uint256 i = 0; i < accounts.length; ++i) {batchBalances[i] = balanceOf(accounts[i], ids[i]);}return batchBalances;}

setApprovalForAll函数

// 设置对operate的授权approve状态function setApprovalForAll(address operator, bool approved) public virtual override {// 调用_setApprovalForAll函数_setApprovalForAll(_msgSender(), operator, approved);}

isApprovedForAll函数

// 获取account地址对operate地址的授权状态function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {return _operatorApprovals[account][operator];}

safeTransferFrom函数

// 转移mount数量的id代币 从from地址到to地址function safeTransferFrom(address from,address to,uint256 id,uint256 amount,bytes memory data) public virtual override {// 检查from是否是合约调用者地址,或者from账号有approve授权给合约调用者require(from == _msgSender() || isApprovedForAll(from, _msgSender()),"ERC1155: caller is not token owner or approved");// 调用_safeTransferFrom函数,转移代币_safeTransferFrom(from, to, id, amount, data);}

safeBatchTransferFrom函数

// 批量转移代币function safeBatchTransferFrom(address from,address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) public virtual override {// 检查from是否是合约调用者地址,或者from账号有approve授权给合约调用者require(from == _msgSender() || isApprovedForAll(from, _msgSender()),"ERC1155: caller is not token owner or approved");// 调用_safeBatchTransferFrom函数转移代币_safeBatchTransferFrom(from, to, ids, amounts, data);}

_safeTransferFrom函数

// 转移mount数量的id代币 从from地址到to地址function _safeTransferFrom(address from,address to,uint256 id,uint256 amount,bytes memory data) internal virtual {// 检查to地址是否为空地址require(to != address(0), "ERC1155: transfer to the zero address");// 获取当前合约调用者地址address operator = _msgSender();// 获取id列表,该列表只有一个元素 ids[0] = iduint256[] memory ids = _asSingletonArray(id);// 获取amount列表该列表只有一个元素 amounts[0] = amountuint256[] memory amounts = _asSingletonArray(amount);// 转移代币前执行的函数_beforeTokenTransfer(operator, from, to, ids, amounts, data);// 获取from地址的id代币数量uint256 fromBalance = _balances[id][from];// 检查 from地址的id代币数量fromBalance 是否大于等于要转移的数量amountrequire(fromBalance >= amount, "ERC1155: insufficient balance for transfer");// 减去转移走的数量 重新写入代币数量unchecked {_balances[id][from] = fromBalance - amount;}// 加上得到的代币数量,重新写入值_balances[id][to] += amount;// 触发转移单个代币时间,记录信息emit TransferSingle(operator, from, to, id, amount);// 代币转移后执行函数_afterTokenTransfer(operator, from, to, ids, amounts, data);// 检查接收的合约地址是否实现IERC1155Receiver接口_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);}

_safeBatchTransferFrom函数

function _safeBatchTransferFrom(address from,address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) internal virtual {// 检查账号列表长度与代币id列表长度一致require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");// 检查to地址是否为空地址require(to != address(0), "ERC1155: transfer to the zero address");// 获取当前合约调用者地址address operator = _msgSender();// 代币转移前执行函数_beforeTokenTransfer(operator, from, to, ids, amounts, data);for (uint256 i = 0; i < ids.length; ++i) {// 获取代币iduint256 id = ids[i];// 获取转移数量值uint256 amount = amounts[i];// 获取当前账号与代币对应数量uint256 fromBalance = _balances[id][from];// 检查余额是否大于转移数量require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");// 减去转移数量,重新写入值unchecked {_balances[id][from] = fromBalance - amount;}// 加上转移数量,重新写入值_balances[id][to] += amount;}// 触发转移单个代币事件,记录信息emit TransferBatch(operator, from, to, ids, amounts);// 代币转移后执行函数_afterTokenTransfer(operator, from, to, ids, amounts, data);// 检查接收的合约地址是否实现IERC1155Receiver接口_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);}

_setURI函数

// 设置新uri地址function _setURI(string memory newuri) internal virtual {_uri = newuri;}

_mint函数

// 铸造amount数量id代币给to地址function _mint(address to,uint256 id,uint256 amount,bytes memory data) internal virtual {// 检查to是否是空地址require(to != address(0), "ERC1155: mint to the zero address");// 获取合约调用者地址address operator = _msgSender();// 获取id列表,该列表只有一个元素 ids[0] = iduint256[] memory ids = _asSingletonArray(id);// 获取amount列表该列表只有一个元素 amounts[0] = amountuint256[] memory amounts = _asSingletonArray(amount);// 代币转移前执行函数_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);// 增加代币余额_balances[id][to] += amount;// 触发转移单个代币事件,记录信息emit TransferSingle(operator, address(0), to, id, amount);// 代币转移后执行函数_afterTokenTransfer(operator, address(0), to, ids, amounts, data);// 检查接收的合约地址是否实现IERC1155Receiver接口_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);}

_mintBatch函数

// 铸造amounts列表对应ids列表代币给to地址function _mintBatch(address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) internal virtual {// 检查to是否是空地址require(to != address(0), "ERC1155: mint to the zero address");// 检查账号列表长度与代币id列表长度一致require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");// 获取当前合约调用者地址address operator = _msgSender();// 代币转移前执行函数_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);// 增加代币余额for (uint256 i = 0; i < ids.length; i++) {_balances[ids[i]][to] += amounts[i];}// 触发转移单个代币事件,记录信息emit TransferBatch(operator, address(0), to, ids, amounts);// 代币转移后执行函数_afterTokenTransfer(operator, address(0), to, ids, amounts, data);// 检查接收的合约地址是否实现IERC1155Receiver接口_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);}

_burn函数

//销毁from地址的id代币function _burn(address from,uint256 id,uint256 amount) internal virtual {// 检查from地址 不为空地址require(from != address(0), "ERC1155: burn from the zero address");// 获取当前合约调用者地址address operator = _msgSender();// 获取id列表,该列表只有一个元素 ids[0] = iduint256[] memory ids = _asSingletonArray(id);// 获取amount列表该列表只有一个元素 amounts[0] = amountuint256[] memory amounts = _asSingletonArray(amount);// 代币转移前执行函数_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");// 获取from账号id代币余额uint256 fromBalance = _balances[id][from];// 检查余额是否大于等于销毁数量require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");// 减去销毁数量,重新写入值unchecked {_balances[id][from] = fromBalance - amount;}// 触发转移单个代币事件,记录信息emit TransferSingle(operator, from, address(0), id, amount);// 代币转移后执行函数_afterTokenTransfer(operator, from, address(0), ids, amounts, "");}

_burnBatch函数

// 批量销毁地址拥有的各种id代币function _burnBatch(address from,uint256[] memory ids,uint256[] memory amounts) internal virtual {// 检查from地址 不为空地址require(from != address(0), "ERC1155: burn from the zero address");// 检查账号列表长度与代币id列表长度一致require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");// 获取当前合约调用者地址address operator = _msgSender();// 代币转移前执行函数_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");// 销毁代币for (uint256 i = 0; i < ids.length; i++) {// 获取代币iduint256 id = ids[i];// 获取销毁数量uint256 amount = amounts[i];// 获取代币余额uint256 fromBalance = _balances[id][from];// 检查余额是否大于等于销毁数量require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");// 减去转销毁量,重新写入值unchecked {_balances[id][from] = fromBalance - amount;}}// 触发批量转移代币事件,记录信息emit TransferBatch(operator, from, address(0), ids, amounts);// 代币转移后执行函数_afterTokenTransfer(operator, from, address(0), ids, amounts, "");}

_setApprovalForAll函数

// 设置owner对operate的授权状态function _setApprovalForAll(address owner,address operator,bool approved) internal virtual {// 检查 owner地址和operate地址是否相同require(owner != operator, "ERC1155: setting approval status for self");// 设置对operate的授权approve状态_operatorApprovals[owner][operator] = approved;// 触发授权事件emit ApprovalForAll(owner, operator, approved);}

_beforeTokenTransfer函数

// 代币转移前函数function _beforeTokenTransfer(address operator,address from,address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) internal virtual {}

_afterTokenTransfer函数

// 代币转移后执行函数function _afterTokenTransfer(address operator,address from,address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) internal virtual {}

_doSafeTransferAcceptanceCheck函数

// 如果to是普通地址则返回ture,如果to是合约地址则检查该合约是否实现onERC1155Received接口function _doSafeTransferAcceptanceCheck(address operator,address from,address to,uint256 id,uint256 amount,bytes memory data) private {if (to.isContract()) {try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {if (response != IERC1155Receiver.onERC1155Received.selector) {revert("ERC1155: ERC1155Receiver rejected tokens");}} catch Error(string memory reason) {revert(reason);} catch {revert("ERC1155: transfer to non-ERC1155Receiver implementer");}}}

_doSafeBatchTransferAcceptanceCheck函数

// 如果to是普通地址则返回ture,如果to是合约地址则检查该合约是否实现onERC1155Received接口function _doSafeBatchTransferAcceptanceCheck(address operator,address from,address to,uint256[] memory ids,uint256[] memory amounts,bytes memory data) private {if (to.isContract()) {try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {revert("ERC1155: ERC1155Receiver rejected tokens");}} catch Error(string memory reason) {revert(reason);} catch {revert("ERC1155: transfer to non-ERC1155Receiver implementer");}}}

_asSingletonArray函数

// 返回包含单个元素的列表function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {uint256[] memory array = new uint256[](1);array[0] = element;return array;}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。