// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"../utils/EnumerableSet.sol";
import"../utils/Address.sol";
import"../utils/Context.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/abstractcontractAccessControlisContext{
usingEnumerableSetforEnumerableSet.AddressSet;
usingAddressforaddress;
structRoleData {
EnumerableSet.AddressSet members;
bytes32 adminRole;
}
mapping (bytes32=> RoleData) private _roles;
bytes32publicconstant DEFAULT_ADMIN_ROLE =0x00;
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/eventRoleAdminChanged(bytes32indexed role, bytes32indexed previousAdminRole, bytes32indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {_setupRole}.
*/eventRoleGranted(bytes32indexed role, addressindexed account, addressindexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/eventRoleRevoked(bytes32indexed role, addressindexed account, addressindexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/functionhasRole(bytes32 role, address account) publicviewreturns (bool) {
return _roles[role].members.contains(account);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/functiongetRoleMemberCount(bytes32 role) publicviewreturns (uint256) {
return _roles[role].members.length();
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/functiongetRoleMember(bytes32 role, uint256 index) publicviewreturns (address) {
return _roles[role].members.at(index);
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/functiongetRoleAdmin(bytes32 role) publicviewreturns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/functiongrantRole(bytes32 role, address account) publicvirtual{
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/functionrevokeRole(bytes32 role, address account) publicvirtual{
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/functionrenounceRole(bytes32 role, address account) publicvirtual{
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/function_setupRole(bytes32 role, address account) internalvirtual{
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/function_setRoleAdmin(bytes32 role, bytes32 adminRole) internalvirtual{
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function_grantRole(bytes32 role, address account) private{
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, _msgSender());
}
}
function_revokeRole(bytes32 role, address account) private{
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, _msgSender());
}
}
}
Contract Source Code
File 2 of 25: Address.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.8.0;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in// construction, since the code is only stored at the end of the// constructor execution.uint256 size;
// solhint-disable-next-line no-inline-assemblyassembly { size :=extcodesize(account) }
return size >0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data, stringmemory errorMessage) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target, bytesmemory data, uint256 value) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target, bytesmemory data, uint256 value, stringmemory errorMessage) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytesmemory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data, stringmemory errorMessage) internalviewreturns (bytesmemory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytesmemory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data, stringmemory errorMessage) internalreturns (bytesmemory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytesmemory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function_verifyCallResult(bool success, bytesmemory returndata, stringmemory errorMessage) privatepurereturns(bytesmemory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly// solhint-disable-next-line no-inline-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (addresspayable) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytesmemory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691returnmsg.data;
}
}
Contract Source Code
File 6 of 25: ERC165.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/abstractcontractERC165isIERC165{
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/bytes4privateconstant _INTERFACE_ID_ERC165 =0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/mapping(bytes4=>bool) private _supportedInterfaces;
constructor () internal{
// Derived contracts need only register support for their own interfaces,// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/function_registerInterface(bytes4 interfaceId) internalvirtual{
require(interfaceId !=0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] =true;
}
}
Contract Source Code
File 7 of 25: EnumerableSet.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/libraryEnumerableSet{
// To implement this library for multiple types with as little code// repetition as possible, we write it in terms of a generic Set type with// bytes32 values.// The Set implementation uses private functions, and user-facing// implementations (such as AddressSet) are just wrappers around the// underlying Set.// This means that we can only create new EnumerableSets for types that fit// in bytes32.structSet {
// Storage of set valuesbytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0// means a value is not in the set.mapping (bytes32=>uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/function_add(Set storage set, bytes32 value) privatereturns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/function_remove(Set storage set, bytes32 value) privatereturns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slotuint256 valueIndex = set._indexes[value];
if (valueIndex !=0) { // Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 toDeleteIndex = valueIndex -1;
uint256 lastIndex = set._values.length-1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex +1; // All indexes are 1-based// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slotdelete set._indexes[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/function_contains(Set storage set, bytes32 value) privateviewreturns (bool) {
return set._indexes[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/function_length(Set storage set) privateviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/function_at(Set storage set, uint256 index) privateviewreturns (bytes32) {
require(set._values.length> index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32SetstructBytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Bytes32Set storage set, bytes32 value) internalviewreturns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(Bytes32Set storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Bytes32Set storage set, uint256 index) internalviewreturns (bytes32) {
return _at(set._inner, index);
}
// AddressSetstructAddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(AddressSet storage set, address value) internalreturns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(AddressSet storage set, address value) internalreturns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(AddressSet storage set, address value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(AddressSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(AddressSet storage set, uint256 index) internalviewreturns (address) {
returnaddress(uint160(uint256(_at(set._inner, index))));
}
// UintSetstructUintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(UintSet storage set, uint256 value) internalreturns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(UintSet storage set, uint256 value) internalreturns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(UintSet storage set, uint256 value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/functionlength(UintSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(UintSet storage set, uint256 index) internalviewreturns (uint256) {
returnuint256(_at(set._inner, index));
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.8.0;import"../../introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/interfaceIERC1155isIERC165{
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/eventTransferSingle(addressindexed operator, addressindexedfrom, addressindexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/eventTransferBatch(addressindexed operator, addressindexedfrom, addressindexed to, uint256[] ids, uint256[] values);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/eventApprovalForAll(addressindexed account, addressindexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/eventURI(string value, uint256indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/functionbalanceOf(address account, uint256 id) externalviewreturns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/functionbalanceOfBatch(address[] calldata accounts, uint256[] calldata ids) externalviewreturns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/functionsetApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/functionisApprovedForAll(address account, address operator) externalviewreturns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/functionsafeTransferFrom(addressfrom, address to, uint256 id, uint256 amount, bytescalldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/functionsafeBatchTransferFrom(addressfrom, address to, uint256[] calldata ids, uint256[] calldata amounts, bytescalldata data) external;
}
Contract Source Code
File 11 of 25: IERC1155MetadataURI.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.8.0;import"./IERC1155.sol";
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
*
* _Available since v3.1._
*/interfaceIERC1155MetadataURIisIERC1155{
/**
* @dev Returns the URI for token type `id`.
*
* If the `\{id\}` substring is present in the URI, it must be replaced by
* clients with the actual token type ID.
*/functionuri(uint256 id) externalviewreturns (stringmemory);
}
Contract Source Code
File 12 of 25: IERC1155Receiver.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"../../introspection/IERC165.sol";
/**
* _Available since v3.1._
*/interfaceIERC1155ReceiverisIERC165{
/**
@dev Handles the receipt of a single ERC1155 token type. This function is
called at the end of a `safeTransferFrom` after the balance has been updated.
To accept the transfer, this must return
`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
(i.e. 0xf23a6e61, or its own function selector).
@param operator The address which initiated the transfer (i.e. msg.sender)
@param from The address which previously owned the token
@param id The ID of the token being transferred
@param value The amount of tokens being transferred
@param data Additional data with no specified format
@return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/functiononERC1155Received(address operator,
addressfrom,
uint256 id,
uint256 value,
bytescalldata data
)
externalreturns(bytes4);
/**
@dev Handles the receipt of a multiple ERC1155 token types. This function
is called at the end of a `safeBatchTransferFrom` after the balances have
been updated. To accept the transfer(s), this must return
`bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
(i.e. 0xbc197c81, or its own function selector).
@param operator The address which initiated the batch transfer (i.e. msg.sender)
@param from The address which previously owned the token
@param ids An array containing ids of each token being transferred (order and length must match values array)
@param values An array containing amounts of each token being transferred (order and length must match ids array)
@param data Additional data with no specified format
@return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/functiononERC1155BatchReceived(address operator,
addressfrom,
uint256[] calldata ids,
uint256[] calldata values,
bytescalldata data
)
externalreturns(bytes4);
}
Contract Source Code
File 13 of 25: IERC165.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 14 of 25: IERC2981.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.7.5;pragmaexperimentalABIEncoderV2;interfaceIERC2981{
/// @notice Called with the sale price to determine how much royalty// is owed and to whom./// @param _tokenId - the NFT asset queried for royalty information/// @param _salePrice - the sale price of the NFT asset specified by _tokenId/// @return receiver - address of who should be sent the royalty payment/// @return royaltyAmount - the royalty payment amount for _salePricefunctionroyaltyInfo(uint256 _tokenId,
uint256 _salePrice
) externalviewreturns (address receiver,
uint256 royaltyAmount
);
}
// SPDX-License-Identifier: MITpragmasolidity ^0.7.5;pragmaexperimentalABIEncoderV2;import"./INFTCollection.sol";
import"../Asset.sol";
import"./NFTCollectionBurnable.sol";
import"../RoyaltyFee.sol";
import"../IDATSNFTCollection.sol";
/**
* @title NFTAssetCollection
* NFTAssetCollection - ERC1155 contract that creates capped assets and stores their configuration params and metadata
*/abstractcontractNFTAssetCollectionisIDATSNFTCollection,
INFTCollection,
NFTCollectionBurnable,
Asset,
RoyaltyFee{
mapping(string=>uint256) public assetCap;
mapping(string=>uint256) public assetWeight;
mapping(string=>address) public assetRoyaltyReceiver;
mapping(string=>uint256) public assetRoyaltyFee;
mapping(string=> NFTCollectionAssetData) public assets;
mapping(uint256=>string) private _numericalIdAsset;
// Contract namestringpublic name;
stringpublic symbol;
stringpublicoverride collectionId;
// used to save all asset Ids, to be able to iterate over themstring[] public assetIds;
constructor(INFTCollection.NFTCollectionData memory _data)
NFTCollectionBase(_data.baseUri)
{
name = _data.name;
symbol = _data.symbol;
collectionId = _data.collectionId;
// register the supported interfaces to conform to ERC2981 via ERC165
_registerInterface(_INTERFACE_ID_ERC2981);
_registerInterface(type(IDATSNFTCollection).interfaceId);
}
/**
* @dev Creates a new asset type
* @param _cmd A CreateAssetCommand with the following parameters:
* _id The id of the asset to create (must not currently exist).
* _cap Maximum amount of total supply
* _assetData Data of the new asset
* _weight The weight of the new asset, may be 0
* _royaltyReceiver The address which will receive the royalty
* _royaltyFee The royalty fee in percent
*/functioncreateAsset(CreateAssetCommand memory _cmd) public{
_checkValidRoyaltyFee(_cmd.royaltyFee);
_onlyManager();
require(!_existAsset(_cmd.id), "Asset id already exists");
if (assetIds.length>0) {
if (assetWeight[assetIds[0]] ==0) {
require(_cmd.weight ==0, "Existing assets have no weight, asset with weight not allowed");
}
else {
require(_cmd.weight >0, "Existing assets have weight, asset without weight not allowed");
}
}
require(_cmd.royaltyReceiver !=address(0), "Royalty receiver is zero");
assets[_cmd.id] = _cmd.assetData;
assetCap[_cmd.id] = _cmd.cap;
assetWeight[_cmd.id] = _cmd.weight;
_setRoyaltyReceiver(_cmd.id, _cmd.royaltyReceiver);
_setRoyaltyFee(_cmd.id, _cmd.royaltyFee);
_numericalIdAsset[calculateAssetNumericalId(_cmd.id)] = _cmd.id;
assetIds.push(_cmd.id);
emit AssetCreated(
_cmd.id,
_cmd.cap,
_cmd.assetData,
_cmd.weight,
_cmd.royaltyReceiver,
_cmd.royaltyFee
);
}
functionmodifyWeight(stringmemory _id, uint256 _newWeight) public{
_onlyManager();
_checkAssetExists(_id);
require(assetWeight[_id] != _newWeight, "Weight not changed");
uint256 oldWeight = assetWeight[_id];
assetWeight[_id] = _newWeight;
emit AssetWeightModified(_id, oldWeight, _newWeight);
}
functionuriAsset(stringmemory _assetId)
publicviewreturns (stringmemory)
{
_checkAssetExists(_assetId);
// We have to convert string to bytes to check for existenceif (
keccak256(abi.encodePacked((assets[_assetId].uri))) !=keccak256(abi.encodePacked(("NOT_BASE_URI")))
) {
return assets[_assetId].uri;
} else {
return _uri;
}
}
/**
* @dev Returns the cap on the asset's total supply.
*/functioncap(stringmemory _id) publicviewvirtualreturns (uint256) {
return assetCap[_id];
}
/**
* @dev Returns the weight of the asset.
*/functionweight(stringmemory _id) publicviewvirtualreturns (uint256) {
return assetWeight[_id];
}
/**
* @dev Returns whether the specified asset exists by checking to see if it has totalSupply
* @param _id uint256 ID of the asset to query the existence of
* @return bool whether the asset exists
*/functionexists(stringmemory _id) externalviewreturns (bool) {
return _existAsset(_id);
}
/**
* @dev Sets a new URI for all asset types, by relying on the asset type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
* @param _newURI New URI for all assets
*/functionsetURI(stringmemory _newURI) public{
_onlyManager();
_setURI(_newURI);
emit BaseAssetCollectionURISet(_newURI);
}
/**
* @dev Will update the URI for the asset
* @param _assetId The asset to update. _msgSender() must be the minter.
* @param _newURI New URI for the asset.
*/functionsetAssetCustomUri(stringmemory _assetId, stringmemory _newURI) public{
_onlyManager();
_checkAssetExists(_assetId);
assets[_assetId].uri = _newURI;
emit AssetCustomURISet(_newURI, _assetId);
}
/**
* @dev Pauses all asset transfers.
*
* See {ERC721Pausable} and {Pausable-_pause}.
*
* Requirements:
*
* - the caller must have the `DEFAULT_ADMIN_ROLE`.
*/functionpause() publicvirtual{
_onlyManager();
_pause();
}
functionassetsInCollection() externalviewoverridereturns (string[] memory) {
string[] memory _assetsInCollection =newstring[](assetIds.length);
for (uint256 i =0; i < _assetsInCollection.length; i++) {
_assetsInCollection[i] = assetIds[i];
}
return _assetsInCollection;
}
/**
* @dev Unpauses all asset transfers.
*
* See {ERC721Pausable} and {Pausable-_unpause}.
*
* Requirements:
*
* - the caller must have the `DEFAULT_ADMIN_ROLE`.
*/functionunpause() publicvirtual{
_onlyManager();
_unpause();
}
function_existAsset(stringmemory _id) internalviewreturns (bool) {
return assetCap[_id] >0;
}
functioncalculateAssetNumericalId(stringmemory _assetId)
publicpurereturns (uint256)
{
returnuint256(keccak256(abi.encodePacked(_assetId)));
}
functionmodifyRoyaltyReceiver(stringmemory _assetId, address _newRoyaltyReceiver) publicoverride{
_onlyManager();
super.modifyRoyaltyReceiver(_assetId, _newRoyaltyReceiver);
}
functionmodifyRoyaltyFee(stringmemory _assetId, uint256 _newRoyaltyFee) publicoverride{
_onlyManager();
super.modifyRoyaltyFee(_assetId, _newRoyaltyFee);
}
functionauthorizeAssetBurner(address _burner
) publicvirtualoverride(BurnerRole, IDATSNFTCollection) returns (bool) {
returnsuper.authorizeAssetBurner(_burner);
}
functionburn(address _account,
stringmemory _assetId,
uint256 _tokenId
) publicvirtualoverride(NFTCollectionBurnable, IDATSNFTCollection) {
super.burn(_account, _assetId, _tokenId);
}
functionburnBatch(address _account,
stringmemory _assetId,
uint256[] memory _tokenIds
) publicvirtualoverride(NFTCollectionBurnable, IDATSNFTCollection) {
super.burnBatch(_account, _assetId, _tokenIds);
}
function_checkTransferIsApproved(address _from) internaloverrideview{
require(
_from == _msgSender() || isApprovedForAll(_from, _msgSender()) ||
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()) || isAssetManager(_msgSender()),
"Not approved"
);
}
function_getRoyaltyReceiverById(uint256 _numericalId) internalviewoverridereturns (address) {
return getRoyaltyReceiver(_numericalIdAsset[_numericalId]);
}
functiongetRoyaltyReceiver(stringmemory _assetId) publicviewoverridereturns (address) {
return assetRoyaltyReceiver[_assetId];
}
function_setRoyaltyReceiver(stringmemory _assetId, address _newRoyaltyReceiver) internaloverride{
assetRoyaltyReceiver[_assetId] = _newRoyaltyReceiver;
}
function_getRoyaltyFeeById(uint256 _numericalId) internalviewoverridereturns (uint256) {
return getRoyaltyFee(_numericalIdAsset[_numericalId]);
}
functiongetRoyaltyFee(stringmemory _assetId) publicviewoverridereturns (uint256) {
return assetRoyaltyFee[_assetId];
}
function_setRoyaltyFee(stringmemory _assetId, uint256 _newRoyaltyFee) internaloverride{
assetRoyaltyFee[_assetId] = _newRoyaltyFee;
}
function_checkAssetExists(stringmemory _id) internalview{
require(_existAsset(_id), "Non existent asset");
}
}
Contract Source Code
File 18 of 25: NFTCollection.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.7.5;pragmaexperimentalABIEncoderV2;import"./NFTCollectionMintable.sol";
/**
* @dev Extension of {ERC1155} that allows token holders to destroy both their
* own tokens and those that they have been approved to use.
*
* _Available since v3.1._
*/contractNFTCollectionisNFTCollectionMintable{
usingSafeMathforuint256;
//solhint-disable no-empty-blocksconstructor(
INFTCollection.NFTCollectionData memory _data,
bool _autoIncrementalCollection
) NFTCollectionMintable(_data, _autoIncrementalCollection) {}
functionburn(address _account,
stringmemory _assetId,
uint256 _tokenId
) publicoverride{
uint256 nftCollectionTokenId = calculateNftCollectionTokenId(_assetId, _tokenId);
assetSupply[tokenAsset[nftCollectionTokenId]] = assetSupply[tokenAsset[nftCollectionTokenId]].sub(1);
_updateAssetAmount(_assetId, _account, address(0), 1);
super.burn(_account, _assetId, _tokenId);
emit NFTCollectionBurn(_account, _assetId, _tokenId, nftCollectionTokenId) ;
}
functionburnBatch(address _account,
stringmemory _assetId,
uint256[] memory _tokenIds
) publicoverride{
uint256[] memory nftCollectionTokenIds =newuint256[](_tokenIds.length);
_updateAssetAmount(_assetId, _account, address(0), _tokenIds.length);
for (uint256 i =0; i < _tokenIds.length; i++) {
nftCollectionTokenIds[i] = calculateNftCollectionTokenId(_assetId, _tokenIds[i]);
assetSupply[tokenAsset[nftCollectionTokenIds[i]]] =
assetSupply[tokenAsset[nftCollectionTokenIds[i]]].sub(1);
}
super.burnBatch(_account, _assetId, _tokenIds);
emit NFTCollectionBurnBatch(_account, _assetId, _tokenIds, nftCollectionTokenIds);
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/functionsafeTransferFrom(address _from,
address _to,
uint256 _internalId,
uint256 _amount,
bytesmemory _data
) publicoverride{
require(_amount ==1, "amount must be 1");
_checkNotPaused();
_updateAssetAmount(_tokenMappings[_internalId], _from, _to, 1);
_safeTransferFrom(_from, _to, _internalId, 1, _data);
}
functionsafeTransferFrom(address _from,
address _to,
stringmemory _assetId,
uint256 _tokenId,
bytesmemory _data
)
publicoverride{
_checkNotPaused();
_updateAssetAmount(_assetId, _from, _to, 1);
uint256 internalId = calculateNftCollectionTokenId(_assetId, _tokenId);
_safeTransferFrom(_from, _to, internalId, 1, _data);
emit NFTCollectionTransfer(_from, _to, _assetId, _tokenId, internalId);
}
functionsafeBatchTransferFrom(address _from,
address _to,
stringmemory _assetId,
uint256 [] memory _tokenIds,
bytesmemory _data
)
publicoverride{
_checkNotPaused();
_updateAssetAmount(_assetId, _from, _to, _tokenIds.length);
uint256[] memory nftCollectionTokenIds =newuint256[](_tokenIds.length);
uint256[] memory amounts =newuint256[](_tokenIds.length);
for (uint256 i =0; i < _tokenIds.length; i++) {
nftCollectionTokenIds[i] = calculateNftCollectionTokenId(_assetId, _tokenIds[i]);
amounts[i] =1;
}
super.safeBatchTransferFrom(_from, _to, nftCollectionTokenIds, amounts, _data);
emit NFTCollectionTransferBatch(_from, _to, _assetId, _tokenIds, nftCollectionTokenIds);
}
functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) publicoverride{
_checkNotPaused();
super.safeBatchTransferFrom(from, to, ids, amounts, data);
}
functionwithdraw(NFTCollectionWithdrawCommand calldata withdrawCommand) externaloverride{
safeTransferFrom(
withdrawCommand.from,
withdrawCommand.to,
withdrawCommand.assetId,
withdrawCommand.tokenId,
bytes("")
);
emit Withdraw(
withdrawCommand.operationId,
withdrawCommand.from,
withdrawCommand.to,
withdrawCommand.assetId,
withdrawCommand.tokenId
);
}
functionauthorizeAssetBurner(address _burner)
publicoverride(NFTAssetCollection) returns (bool)
{
_onlyAdmin();
returnsuper.authorizeAssetBurner(_burner);
}
functionrevokeAssetBurner(address _burner) publicoverridereturns (bool) {
_onlyAdmin();
returnsuper.revokeAssetBurner(_burner);
}
/**
* @dev See {IERC1155MetadataURI-uri}.
*
* This implementation returns the same URI for *all* token types. It relies
* on the token type ID substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/functionuri(uint256 _internalId) publicviewoverridereturns (stringmemory) {
stringmemory _assetId = _tokenMappings[_internalId];
stringmemory _assetUri = uriAsset(_assetId);
if (!_isEmptyString(_assetUri)) {
return _assetUri;
}
returnstring(abi.encodePacked(_uri, "/", _assetId));
}
function_updateAssetAmount(stringmemory _assetId, address _from, address _to, uint256 _amount) private{
if (_from !=address(0)) {
_assetAmountByUsers[_assetId][_from] =
_assetAmountByUsers[_assetId][_from].sub(_amount, "Insufficient balance");
}
if (_to !=address(0)) {
_assetAmountByUsers[_assetId][_to] = _assetAmountByUsers[_assetId][_to].add(_amount);
}
}
function_checkNotPaused() internalview{
if (!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) {
require(!paused(), "Token transfer is paused");
}
}
function_checkApprovedToBurn(address _burner, address _account) internaloverrideview{
_checkNotPaused();
returnsuper._checkApprovedToBurn(_burner, _account);
}
function_isEmptyString(stringmemory _str) privatepurereturns (bool) {
bytesmemory strBytes =bytes(_str);
return strBytes.length==0;
}
}
Contract Source Code
File 19 of 25: NFTCollectionBase.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.7.5;pragmaexperimentalABIEncoderV2;import"@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import"@openzeppelin/contracts/token/ERC1155/IERC1155MetadataURI.sol";
import"@openzeppelin/contracts/utils/Address.sol";
import"@openzeppelin/contracts/utils/Context.sol";
import"@openzeppelin/contracts/utils/Pausable.sol";
import"@openzeppelin/contracts/introspection/ERC165.sol";
import"@openzeppelin/contracts/math/SafeMath.sol";
import"@openzeppelin/contracts/utils/Strings.sol";
/**
*
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
*
* _Available since v3.1._
*/abstractcontractNFTCollectionBaseisContext, ERC165, Pausable, IERC1155, IERC1155MetadataURI{
usingSafeMathforuint256;
usingAddressforaddress;
// Mapping from token ID to account balancesmapping(uint256=>mapping(address=>uint256)) private _balances;
// Mapping from account to operator approvalsmapping(address=>mapping(address=>bool)) private _operatorApprovals;
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.jsonstringinternal _uri;
/*
* bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
* bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
* bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
*
* => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
* 0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
*/bytes4privateconstant _INTERFACE_ID_ERC1155 =0xd9b67a26;
/*
* bytes4(keccak256('uri(uint256)')) == 0x0e89341c
*/bytes4privateconstant _INTERFACE_ID_ERC1155_METADATA_URI =0x0e89341c;
/**
* @dev See {_setURI}.
*/constructor(stringmemory uri_) {
_setURI(uri_);
// register the supported interfaces to conform to ERC1155 via ERC165
_registerInterface(_INTERFACE_ID_ERC1155);
// register the supported interfaces to conform to ERC1155MetadataURI via ERC165
_registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
}
/**
* @dev See {IERC1155-balanceOf}.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/functionbalanceOf(address account, uint256 id)
publicviewvirtualoverridereturns (uint256)
{
_checkNotZeroAddress(account);
return _balances[id][account];
}
/**
* @dev See {IERC1155-balanceOfBatch}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/functionbalanceOfBatch(address[] memory accounts, uint256[] memory ids)
publicviewvirtualoverridereturns (uint256[] memory)
{
_checkArrayLengths(accounts.length, ids.length);
uint256[] memory batchBalances =newuint256[](accounts.length);
for (uint256 i =0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved)
publicvirtualoverride{
require(
_msgSender() != operator,
"Setting approval status for self"
);
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/functionisApprovedForAll(address account, address operator)
publicviewvirtualoverridereturns (bool)
{
return _operatorApprovals[account][operator];
}
function_safeTransferFrom(addressfrom,
address to,
uint256 internalId,
uint256 amount,
bytesmemory data
) internal{
_checkNotZeroAddress(to);
_checkTransferIsApproved(from);
address operator = _msgSender();
_balances[internalId][from] = _balances[internalId][from].sub(
amount,
"Insufficient balance"
);
_balances[internalId][to] = _balances[internalId][to].add(amount);
emit TransferSingle(operator, from, to, internalId, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, internalId, amount, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) publicvirtualoverride{
_checkArrayLengths(ids.length, amounts.length);
_checkNotZeroAddress(to);
_checkTransferIsApproved(from);
address operator = _msgSender();
for (uint256 i =0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
_balances[id][from] = _balances[id][from].sub(
amount,
"Insufficient balance"
);
_balances[id][to] = _balances[id][to].add(amount);
}
emit TransferBatch(operator, from, to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(
operator,
from,
to,
ids,
amounts,
data
);
}
functioncalculateNftCollectionTokenId(stringmemory _assetId,
uint256 _tokenId
) publicpurereturns (uint256) {
returnuint256(keccak256(abi.encodePacked(_assetId, _tokenId)));
}
/**
* @dev Sets a new URI for all token types, by relying on the token type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* By this mechanism, any occurrence of the `\{id\}` substring in either the
* URI or any of the amounts in the JSON file at said URI will be replaced by
* clients with the token type ID.
*
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
* interpreted by clients as
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
* for token type ID 0x4cce0.
*
* See {uri}.
*
* Because these URIs cannot be meaningfully represented by the {URI} event,
* this function emits no events.
*/function_setURI(stringmemory newuri) internalvirtual{
_uri = newuri;
}
/**
* @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/function_mint(address account,
uint256 id,
uint256 amount,
bytesmemory data
) internalvirtual{
_checkNotZeroAddress(account);
address operator = _msgSender();
_balances[id][account] = _balances[id][account].add(amount);
emit TransferSingle(operator, address(0), account, id, amount);
_doSafeTransferAcceptanceCheck(
operator,
address(0),
account,
id,
amount,
data
);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/function_mintBatch(address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) internalvirtual{
_checkNotZeroAddress(to);
_checkArrayLengths(ids.length, amounts.length);
address operator = _msgSender();
for (uint256 i =0; i < ids.length; i++) {
_balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(
operator,
address(0),
to,
ids,
amounts,
data
);
}
/**
* @dev Destroys `amount` tokens of token type `id` from `account`
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens of token type `id`.
*/function_burn(address account,
uint256 id,
uint256 amount
) internalvirtual{
_checkNotZeroAddress(account);
_balances[id][account] = _balances[id][account].sub(
amount,
"Insufficient balance"
);
emit TransferSingle(_msgSender(), account, address(0), id, amount);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
*/function_burnBatch(address account,
uint256[] memory ids,
uint256[] memory amounts
) internalvirtual{
_checkNotZeroAddress(account);
for (uint256 i =0; i < ids.length; i++) {
_balances[ids[i]][account] = _balances[ids[i]][account].sub(
amounts[i],
"Insufficient balance"
);
}
emit TransferBatch(_msgSender(), account, address(0), ids, amounts);
}
function_doSafeTransferAcceptanceCheck(address operator,
addressfrom,
address to,
uint256 id,
uint256 amount,
bytesmemory data
) private{
if (to.isContract()) {
try
IERC1155Receiver(to).onERC1155Received(
operator,
from,
id,
amount,
data
)
returns (bytes4 response) {
if (
response != IERC1155Receiver(to).onERC1155Received.selector
) {
revert("ERC1155Receiver rejected tokens");
}
} catchError(stringmemory reason) {
revert(reason);
} catch {
revert("Transfer to non ERC1155Receiver implementer");
}
}
}
function_doSafeBatchTransferAcceptanceCheck(address operator,
addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) private{
if (to.isContract()) {
try
IERC1155Receiver(to).onERC1155BatchReceived(
operator,
from,
ids,
amounts,
data
)
returns (bytes4 response) {
if (
response !=
IERC1155Receiver(to).onERC1155BatchReceived.selector
) {
revert("ERC1155Receiver rejected tokens");
}
} catchError(stringmemory reason) {
revert(reason);
} catch {
revert("Transfer to non ERC1155Receiver implementer");
}
}
}
function_checkArrayLengths(uint256 _array1Length, uint256 _array2Length) privatepure{
require(_array1Length == _array2Length, "Array length mismatch");
}
function_checkNotZeroAddress(address _adr) privatepure{
require(_adr !=address(0), "Zero address not allowed");
}
function_checkTransferIsApproved(address _from) internalvirtualview;
}
// SPDX-License-Identifier: MITpragmasolidity ^0.7.5;pragmaexperimentalABIEncoderV2;import"@openzeppelin/contracts/math/SafeMath.sol";
import"./NFTAssetCollection.sol";
/**
* @title NFTCollectionMintable
* NFTCollectionMintable - NFTAssetCollection that has totalSupply and can mint
*/abstractcontractNFTCollectionMintableisNFTAssetCollection{
usingSafeMathforuint256;
boolprivate _autoIncremental;
mapping(string=>uint256) public assetSupply;
mapping(uint256=>string) public tokenAsset;
mapping(string=>mapping(address=>uint256)) internal _assetAmountByUsers;
mapping(uint256=>string) internal _tokenMappings;
mapping(string=>uint256) internal _nextTokenIds;
constructor(
INFTCollection.NFTCollectionData memory _data,
bool _autoIncrementalCollection
) NFTAssetCollection(_data) {
_autoIncremental = _autoIncrementalCollection;
}
/**
* @dev Mints some amount of assets to an address
* @param _to Address of the future owner of the asset
* @param _assetId ID of the asset
* @param _tokenId Id of the token to mint
* @param _data Data to pass if receiver is contract
*/functionmint(address _to,
stringmemory _assetId,
uint256 _tokenId,
bytesmemory _data
)
publicvirtualoverridereturns (uint256 id, uint256 internalId)
{
_onlyMinter();
_checkIsNotAutoIncremental();
_checkAssetExists(_assetId);
return _mintAsset(_to, _assetId, _tokenId, _data);
}
/**
* @dev Mint assets for each id in _ids
* @param _to The address to mint assets to
* @param _assetId Id of the asset where new tokens will be minted
* @param _ids Array of ids to mint
* @param _data Data to pass if receiver is contract
*/functionmintBatch(address _to,
stringmemory _assetId,
uint256[] memory _ids,
bytesmemory _data
)
publicoverridereturns (uint256[] memory ids, uint256[] memory internalIds)
{
_onlyMinter();
_checkIsNotAutoIncremental();
_checkAssetExists(_assetId);
uint256 totalNewTokens = _ids.length;
_checkCapNotExceeded(_assetId, totalNewTokens);
uint256[] memory nftCollectionTokenIds =newuint256[](totalNewTokens);
uint256[] memory quantities =newuint256[](totalNewTokens);
for (uint256 i =0; i < totalNewTokens; i++) {
nftCollectionTokenIds[i] = calculateNftCollectionTokenId(
_assetId,
_ids[i]
);
_checkTokenDoesNotExist(_assetId, nftCollectionTokenIds[i]);
tokenAsset[nftCollectionTokenIds[i]] = _assetId;
quantities[i] =1;
}
return _mintBatch(
_to,
_assetId,
_ids,
nftCollectionTokenIds,
quantities,
_data
);
}
/**
* @dev Mints some amount of assets to an address
* @param _to Address of the future owner of the asset
* @param _assetId ID of the asset
* @param _data Data to pass if receiver is contract
*/functionmint(address _to,
stringmemory _assetId,
bytesmemory _data
)
publicvirtualoverridereturns (uint256 id, uint256 internalId)
{
_onlyMinter();
_checkIsAutoIncremental();
_checkAssetExists(_assetId);
uint256 tokenId = _nextTokenIds[_assetId];
_nextTokenIds[_assetId] = _nextTokenIds[_assetId].add(1);
return _mintAsset(_to, _assetId, tokenId, _data);
}
/**
* @dev Mint assets for each id in _ids
* @param _to The address to mint assets to
* @param _assetId Id of the asset where new tokens will be minted
* @param _totalTokens Total of new tokens to mint
* @param _data Data to pass if receiver is contract
*/functionmintBatch(address _to,
stringmemory _assetId,
uint256 _totalTokens,
bytesmemory _data
)
publicvirtualoverridereturns (uint256[] memory ids, uint256[] memory internalIds)
{
_onlyMinter();
_checkIsAutoIncremental();
_checkAssetExists(_assetId);
_checkCapNotExceeded(_assetId, _totalTokens);
uint256[] memory nftCollectionTokenIds =newuint256[](_totalTokens);
uint256[] memory quantities =newuint256[](_totalTokens);
uint256[] memory tokenIds =newuint256[](_totalTokens);
for (uint256 i =0; i < _totalTokens; i++) {
(
nftCollectionTokenIds[i],
tokenIds[i]
) = _generateNewTokenIdForAsset(_assetId);
tokenAsset[nftCollectionTokenIds[i]] = _assetId;
quantities[i] =1;
}
return _mintBatch(
_to,
_assetId,
tokenIds,
nftCollectionTokenIds,
quantities,
_data
);
}
functionbalanceOf(address _account,
stringmemory _assetId,
uint256 _tokenId
) publicviewreturns (uint256 balance) {
returnsuper.balanceOf(
_account,
calculateNftCollectionTokenId(_assetId, _tokenId)
);
}
functionbalanceOf(address _account, stringmemory _assetId)
publicviewreturns (uint256 balance)
{
return _assetAmountByUsers[_assetId][_account];
}
functionbalanceOfBatch(address[] memory _accounts,
stringmemory _assetId,
uint256[] memory _tokenIds
) publicviewreturns (uint256[] memory balances) {
uint256[] memory nftCollectionTokenIds =newuint256[](
_tokenIds.length
);
for (uint256 i =0; i < _tokenIds.length; i++) {
nftCollectionTokenIds[i] = calculateNftCollectionTokenId(
_assetId,
_tokenIds[i]
);
}
return balanceOfBatch(_accounts, nftCollectionTokenIds);
}
functionassetBalanceOf(stringmemory _assetId,
address _to
) externalviewoverridereturns (NFTAssetBalance memory) {
NFTAssetBalance memory assetBalance;
assetBalance.id = _assetId;
assetBalance.weight = assetWeight[_assetId];
assetBalance.balance= _assetAmountByUsers[_assetId][_to];
return assetBalance;
}
functionassetBalanceBatchOf(address _to) externalviewoverridereturns (NFTAssetBalance[] memory) {
NFTAssetBalance[] memory assetBalances =new NFTAssetBalance[](assetIds.length);
for (uint256 i =0; i < assetIds.length; i++) {
assetBalances[i].id = assetIds[i];
assetBalances[i].balance= _assetAmountByUsers[assetIds[i]][_to];
assetBalances[i].weight = assetWeight[assetIds[i]];
}
return assetBalances;
}
/**
* @dev Returns the total quantity for a asset ID
* @param _assetId string ID of the asset to query
* @return amount of asset in existence
*/functiontotalSupply(stringmemory _assetId) publicviewreturns (uint256) {
return assetSupply[_assetId];
}
functionisAutoIncrementalCollection() externalviewoverridereturns (bool) {
return _autoIncremental;
}
functionassetsOf(address _account) externalviewreturns (string[] memory) {
uint256 _numberOfAssetsOfAccount;
// first we need to iterate over all asset ids to calculate how big the resulting array needs to befor (uint256 i =0; i < assetIds.length; i++) {
if (balanceOf(_account, assetIds[i]) >0) {
_numberOfAssetsOfAccount = _numberOfAssetsOfAccount.add(1);
}
}
string[] memory _assetsOfAccount =newstring[](_numberOfAssetsOfAccount);
uint256 _assetsOfAccountIndex;
// now we iterate again over the asset ids to fill the resulting arrayfor (uint256 i =0; i < assetIds.length; i++) {
if (balanceOf(_account, assetIds[i]) >0) {
_assetsOfAccount[_assetsOfAccountIndex] = assetIds[i];
_assetsOfAccountIndex = _assetsOfAccountIndex.add(1);
}
}
return _assetsOfAccount;
}
function_generateNewTokenIdForAsset(stringmemory _assetId)
internalreturns (uint256 nftCollectionTokenId_, uint256 tokenId_)
{
tokenId_ = _nextTokenIds[_assetId];
nftCollectionTokenId_ = calculateNftCollectionTokenId(
_assetId,
tokenId_
);
_nextTokenIds[_assetId] = _nextTokenIds[_assetId].add(1);
}
function_checkTokenDoesNotExist(stringmemory _assetId, uint256 _tokenId) internalview{
require(
keccak256(abi.encodePacked(tokenAsset[_tokenId])) !=keccak256(abi.encodePacked(_assetId)),
"Token already minted"
);
}
function_mintAsset(address _to,
stringmemory _assetId,
uint256 _tokenId,
bytesmemory _data
) internalreturns (uint256 id, uint256 internalId) {
_checkCapNotExceeded(_assetId, 1);
uint256 nftCollectionTokenId = calculateNftCollectionTokenId(
_assetId,
_tokenId
);
_checkTokenDoesNotExist(_assetId, nftCollectionTokenId);
_tokenMappings[nftCollectionTokenId] = _assetId;
assetSupply[_assetId] = assetSupply[_assetId].add(1);
tokenAsset[nftCollectionTokenId] = _assetId;
_assetAmountByUsers[_assetId][_to] = _assetAmountByUsers[_assetId][_to].add(1);
_mint(_to, nftCollectionTokenId, 1, _data);
id = _tokenId;
internalId = nftCollectionTokenId;
emit NFTCollectionMint(_to, _assetId, _tokenId, nftCollectionTokenId);
}
function_mintBatch(address _to,
stringmemory _assetId,
uint256[] memory _ids,
uint256[] memory _nftCollectionTokenIds,
uint256[] memory _quantities,
bytesmemory _data
)
internalreturns (uint256[] memory, uint256[] memory)
{
uint256 totalNewTokens = _ids.length;
assetSupply[_assetId] = assetSupply[_assetId].add(totalNewTokens);
_assetAmountByUsers[_assetId][_to] = _assetAmountByUsers[_assetId][_to]
.add(totalNewTokens);
_mintBatch(_to, _nftCollectionTokenIds, _quantities, _data);
emit NFTCollectionMintBatch(_to, _assetId, _ids, _nftCollectionTokenIds);
return (_ids, _nftCollectionTokenIds);
}
function_checkIsAutoIncremental() internalview{
require(_autoIncremental, "Must be autoIncremental");
}
function_checkIsNotAutoIncremental() internalview{
require(!_autoIncremental, "Must not be autoIncremental");
}
function_checkCapNotExceeded(stringmemory _assetId, uint256 _totalNewTokens) internalview{
require(
totalSupply(_assetId).add(_totalNewTokens) <= assetCap[_assetId],
"Cap exceeded"
);
}
}
Contract Source Code
File 22 of 25: Pausable.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/abstractcontractPausableisContext{
/**
* @dev Emitted when the pause is triggered by `account`.
*/eventPaused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/eventUnpaused(address account);
boolprivate _paused;
/**
* @dev Initializes the contract in unpaused state.
*/constructor () internal{
_paused =false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/functionpaused() publicviewvirtualreturns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/modifierwhenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/modifierwhenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/function_pause() internalvirtualwhenNotPaused{
_paused =true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/function_unpause() internalvirtualwhenPaused{
_paused =false;
emit Unpaused(_msgSender());
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontryAdd(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontrySub(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontryMul(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522if (a ==0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/functiontryDiv(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b ==0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/functiontryMod(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b ==0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/functionmul(uint256 a, uint256 b) internalpurereturns (uint256) {
if (a ==0) return0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b >0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functionmod(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b >0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functionmod(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
return a % b;
}
}
Contract Source Code
File 25 of 25: Strings.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev String operations.
*/libraryStrings{
/**
* @dev Converts a `uint256` to its ASCII `string` representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
// Inspired by OraclizeAPI's implementation - MIT licence// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.solif (value ==0) {
return"0";
}
uint256 temp = value;
uint256 digits;
while (temp !=0) {
digits++;
temp /=10;
}
bytesmemory buffer =newbytes(digits);
uint256 index = digits -1;
temp = value;
while (temp !=0) {
buffer[index--] =bytes1(uint8(48+ temp %10));
temp /=10;
}
returnstring(buffer);
}
}