// SPDX-License-Identifier: MITpragmasolidity ^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 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 (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 2 of 7: ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity >=0.8.0;/// @notice Minimalist and gas efficient standard ERC1155 implementation./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)abstractcontractERC1155{
/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/eventTransferSingle(addressindexed operator,
addressindexedfrom,
addressindexed to,
uint256 id,
uint256 amount
);
eventTransferBatch(addressindexed operator,
addressindexedfrom,
addressindexed to,
uint256[] ids,
uint256[] amounts
);
eventApprovalForAll(addressindexed owner,
addressindexed operator,
bool approved
);
eventURI(string value, uint256indexed id);
/*///////////////////////////////////////////////////////////////
ERC1155 STORAGE
//////////////////////////////////////////////////////////////*/mapping(address=>mapping(uint256=>uint256)) public balanceOf;
mapping(address=>mapping(address=>bool)) public isApprovedForAll;
/*///////////////////////////////////////////////////////////////
METADATA LOGIC
//////////////////////////////////////////////////////////////*/functionuri(uint256 id) publicviewvirtualreturns (stringmemory);
/*///////////////////////////////////////////////////////////////
ERC1155 LOGIC
//////////////////////////////////////////////////////////////*/functionsetApprovalForAll(address operator, bool approved) publicvirtual{
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functionisApproved(address account, address operator)
publicviewvirtualreturns (bool)
{
return isApprovedForAll[account][operator];
}
functionsafeTransferFrom(addressfrom,
address to,
uint256 id,
uint256 amount,
bytesmemory data
) publicvirtual{
require(
msg.sender==from|| isApprovedForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155Received(
msg.sender,
from,
id,
amount,
data
) == ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) publicvirtual{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
require(
msg.sender==from|| isApprovedForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
for (uint256 i =0; i < idsLength; ) {
uint256 id = ids[i];
uint256 amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(
msg.sender,
from,
ids,
amounts,
data
) == ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
functionbalanceOfBatch(address[] memory owners, uint256[] memory ids)
publicviewvirtualreturns (uint256[] memory balances)
{
uint256 ownersLength = owners.length; // Saves MLOADs.require(ownersLength == ids.length, "LENGTH_MISMATCH");
balances =newuint256[](owners.length);
// Unchecked because the only math done is incrementing// the array index counter which cannot possibly overflow.unchecked {
for (uint256 i =0; i < ownersLength; i++) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
/*///////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/functionsupportsInterface(bytes4 interfaceId)
publicpurevirtualreturns (bool)
{
return
interfaceId ==0x01ffc9a7||// ERC165 Interface ID for ERC165
interfaceId ==0xd9b67a26||// ERC165 Interface ID for ERC1155
interfaceId ==0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
}
/*///////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/function_mint(address to,
uint256 id,
uint256 amount,
bytesmemory data
) internal{
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155Received(
msg.sender,
address(0),
id,
amount,
data
) == ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function_batchMint(address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) internal{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i =0; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(
msg.sender,
address(0),
ids,
amounts,
data
) == ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function_batchBurn(addressfrom,
uint256[] memory ids,
uint256[] memory amounts
) internal{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i =0; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function_burn(addressfrom,
uint256 id,
uint256 amount
) internal{
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
/// @notice A generic interface for a contract which properly accepts ERC1155 tokens./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)interfaceERC1155TokenReceiver{
functiononERC1155Received(address operator,
addressfrom,
uint256 id,
uint256 amount,
bytescalldata data
) externalreturns (bytes4);
functiononERC1155BatchReceived(address operator,
addressfrom,
uint256[] calldata ids,
uint256[] calldata amounts,
bytescalldata data
) externalreturns (bytes4);
}
// SPDX-License-Identifier: MIT LICENSEpragmasolidity ^0.8.0;interfaceIRAW{
functiongetBalance(address account,
uint256 id
) externalreturns(uint256);
functionmint(uint256 typeId,
uint256 qty,
address recipient
) external;
functionburn(uint256 typeId,
uint256 qty,
address burnFrom
) external;
functionupdateMintBurns(uint256 typeId,
uint256 mintQty,
uint256 burnQty
) external;
functionsafeTransferFrom(addressfrom,
address to,
uint256 id,
uint256 amount,
bytesmemory data
) external;
functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) external;
}
Contract Source Code
File 5 of 7: Pausable.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"../utils/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() {
_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());
}
}
Contract Source Code
File 6 of 7: Raw.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"@openzeppelin/contracts/security/Pausable.sol";
import"@openzeppelin/contracts/utils/Strings.sol";
import"./ERC1155.sol";
import"./interfaces/IRAW.sol";
import"./interfaces/IEON.sol";
contractRAWisIRAW, ERC1155, Pausable{
usingStringsforuint256;
// struct to store each trait's data for metadata and renderingstructImage {
string name;
string png;
}
structTypeInfo {
uint256 mints;
uint256 burns;
uint256 maxSupply;
uint256 eonExchangeAmt;
}
mapping(uint256=> TypeInfo) private typeInfo;
// storage of each image datamapping(uint256=> Image) public traitData;
// address => allowedToCallFunctionsmapping(address=>bool) private admins;
eventUpdateMintBurns(uint256 typeId, uint256 mintQty, uint256 burnQty);
// reference to the $EON contract for exchange rate if accepted
IEON public eon;
addresspublic auth;
constructor() {
auth =msg.sender;
}
modifieronlyOwner() {
require(msg.sender== auth);
_;
}
/** CRITICAL TO SETUP */modifierrequireContractsSet() {
require(address(eon) !=address(0), "Contracts not set");
_;
}
functionsetContracts(address _eon) externalonlyOwner{
eon = IEON(_eon);
}
/**
* Mint a token - any payment / game logic should be handled in the game contract.
*/functionmint(uint256 typeId,
uint256 qty,
address recipient
) externaloverridewhenNotPaused{
require(admins[msg.sender], "Only admins");
require((typeInfo[typeId].mints + qty) <= typeInfo[typeId].maxSupply, "MaxSupply Minted");
typeInfo[typeId].mints += qty;
_mint(recipient, typeId, qty, "");
}
/**
* Burn a token - any payment / game logic should be handled in the game contract.
*/functionburn(uint256 typeId,
uint256 qty,
address burnFrom
) externaloverridewhenNotPaused{
require(admins[msg.sender], "Only admins");
typeInfo[typeId].burns += qty;
_burn(burnFrom, typeId, qty);
}
functionsetType(uint256 typeId, uint256 maxSupply) externalonlyOwner{
require(typeId !=0, "TypeId cannot be 0");
require(typeInfo[typeId].mints <= maxSupply, "max supply too low");
typeInfo[typeId].maxSupply = maxSupply;
}
// a function to update the mint and burn amounts// to save gas costs of doing both a mint and then// burn when cost is paid from an amount owedfunctionupdateMintBurns(uint256 typeId,
uint256 mintQty,
uint256 burnQty
) external{
require(admins[msg.sender], "Only Admins");
typeInfo[typeId].mints += mintQty;
typeInfo[typeId].burns += burnQty;
emit UpdateMintBurns(typeId, mintQty, burnQty);
}
functionsetExchangeAmt(uint256 typeId, uint256 exchangeAmt)
externalonlyOwner{
require(
typeInfo[typeId].maxSupply >0,
"this type has not been set up"
);
typeInfo[typeId].eonExchangeAmt = exchangeAmt;
}
/**
* enables an address to mint / burn
* @param addr the address to enable
*/functionaddAdmin(address addr) externalonlyOwner{
admins[addr] =true;
}
/**
* disables an address from minting / burning
* @param addr the address to disbale
*/functionremoveAdmin(address addr) externalonlyOwner{
admins[addr] =false;
}
functionsetPaused(bool _paused) externalonlyOwnerrequireContractsSet{
if (_paused) _pause();
else _unpause();
}
functiontransferOwnership(address newOwner) externalonlyOwner{
auth = newOwner;
}
functiongetInfoForType(uint256 typeId)
externalviewreturns (TypeInfo memory)
{
require(typeInfo[typeId].maxSupply >0, "invalid type");
return typeInfo[typeId];
}
functionuri(uint256 typeId) publicviewoverridereturns (stringmemory) {
require(typeInfo[typeId].maxSupply >0, "invalid type");
Image memory img = traitData[typeId];
stringmemory metadata =string(
abi.encodePacked(
'{"name": "',
img.name,
'", "description": "Raw Pytheas resources - All the metadata and images are generated and stored 100% on-chain. No IPFS. NO API. Just the Ethereum blockchain.", "image": "data:image/svg+xml;base64,',
base64(bytes(drawSVG(typeId))),
'", "attributes": []',
"}"
)
);
returnstring(
abi.encodePacked(
"data:application/json;base64,",
base64(bytes(metadata))
)
);
}
functionuploadImage(uint256 typeId, Image calldata image)
externalonlyOwner{
traitData[typeId] = Image(image.name, image.png);
}
functiondrawImage(Image memory image)
internalpurereturns (stringmemory)
{
returnstring(
abi.encodePacked(
'<image x="0" y="0" width="64" height="64" image-rendering="pixelated" preserveAspectRatio="xMidYMid" xlink:href="data:image/png;base64,',
image.png,
'"/>'
)
);
}
functiondrawSVG(uint256 typeId) internalviewreturns (stringmemory) {
stringmemory svgString =string(
abi.encodePacked(drawImage(traitData[typeId]))
);
returnstring(
abi.encodePacked(
'<svg id="alter" width="100%" height="100%" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">',
svgString,
"</svg>"
)
);
}
functiongetBalance(address account,
uint256 id
) publicviewreturns(uint256) {
return ERC1155(address(this)).balanceOf(account, id);
}
functionsafeTransferFrom(addressfrom,
address to,
uint256 id,
uint256 amount,
bytesmemory data
) publicvirtualoverride(ERC1155, IRAW) {
// allow admin contracts to send without approvalif (!admins[msg.sender]) {
require(msg.sender==from|| isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
}
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) publicvirtualoverride(ERC1155, IRAW) {
// allow admin contracts to send without approvaluint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
// allow admin contracts to send without approvalif (!admins[msg.sender]) {
require(msg.sender==from|| isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
}
for (uint256 i =0; i < idsLength; ) {
uint256 id = ids[i];
uint256 amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
/** BASE 64 - Written by Brech Devos */stringinternalconstant TABLE ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
functionbase64(bytesmemory data) internalpurereturns (stringmemory) {
if (data.length==0) return"";
// load the table into memorystringmemory table = TABLE;
// multiply by 4/3 rounded upuint256 encodedLen =4* ((data.length+2) /3);
// add some extra buffer at the end required for the writingstringmemory result =newstring(encodedLen +32);
assembly {
// set the actual output lengthmstore(result, encodedLen)
// prepare the lookup tablelet tablePtr :=add(table, 1)
// input ptrlet dataPtr := data
let endPtr :=add(dataPtr, mload(data))
// result ptr, jump over lengthlet resultPtr :=add(result, 32)
// run over the input, 3 bytes at a timefor {
} lt(dataPtr, endPtr) {
} {
dataPtr :=add(dataPtr, 3)
// read 3 byteslet input :=mload(dataPtr)
// write 4 charactersmstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))
)
resultPtr :=add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))
)
resultPtr :=add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F))))
)
resultPtr :=add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(input, 0x3F))))
)
resultPtr :=add(resultPtr, 1)
}
// padding with '='switchmod(mload(data), 3)
case1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}
}
return result;
}
// For OpenSeasfunctionowner() publicviewvirtualreturns (address) {
return auth;
}
}
Contract Source Code
File 7 of 7: Strings.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal 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);
while (value !=0) {
digits -=1;
buffer[digits] =bytes1(uint8(48+uint256(value %10)));
value /=10;
}
returnstring(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
if (value ==0) {
return"0x00";
}
uint256 temp = value;
uint256 length =0;
while (temp !=0) {
length++;
temp >>=8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _HEX_SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
}