Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 107233832 | 876 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Straylight
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./metadata.sol";
import "./EnumerableMate.sol";
// STRAYLIGHT PROTOCOL v.01
//
// . .
// ., ... .,
// \%%&%%&./
// ,,. /@&&%&&&\ ,,
// *, (##%&&%##) .*.
// (, (#%%%%.) %,
// ,% (#(##(%.(/
// %((#%%%##*
// ..**,*/***///*,..,#%%%%*..,*\\\***\*,**..
// /%#%%
// /###(/%&%/(##%(,
// ,/ (%###%%&%, **
// .#. *@&%###%%&) \\
// / *&&%###%&@# *.
// ,* (%#%###%#?) .*.
// ./%%###%%#,
// .,(((##,.
//
//
/// @title Straylight
/// @notice The main point of interaction for Straylight - relies on Gamboard, Metadata, Turmitesv4 and EnumerableMate
/// @author @brachlandberlin / plsdlr.net
/// @dev facilitates minting, moving of individual turmites, reprogramming and even external logic of turmites and overwrites tokenUri()
contract Straylight is EnumerableMate, Metadata {
event TurmiteReprogramm(uint256 indexed tokenId, bytes12 indexed newrule);
event TurmiteMint(uint256 indexed tokenId, bytes12 indexed rule, uint256 boardId);
uint256 public boardcounter = 0;
uint256 private turmitecounter = 0;
uint256 public maxnumbturmites;
uint256[4] startx = [36, 72, 72, 108];
uint256[4] starty = [72, 36, 108, 72];
address minterContract;
address haecceityContract;
address admin;
mapping(uint256 => bool) public haecceity;
constructor(
address _minterContract,
uint256 maxAmount,
string memory network
) Metadata(network) EnumerableMate("Straylight", "STR") {
minterContract = _minterContract;
maxnumbturmites = maxAmount;
admin = msg.sender;
}
/// @dev public Mint function should only be called from external Minter Contract
/// @param mintTo the address the token should be minted to
/// @param rule the inital rule the turmite is minted with
/// @param moves the inital number of rules the turmite is minted with
function publicmint(
address mintTo,
bytes12 rule,
uint256 moves
) external {
require(turmitecounter < maxnumbturmites, "MINT_OVER");
require(validateNewRule(rule) == true, "INVALID_RULE");
require(msg.sender == minterContract, "ONLY_MINTABLE_FROM_MINT_CONTRACT");
boardcounter = (turmitecounter / 4) + 1;
uint256 startposx = startx[turmitecounter % 4];
uint256 startposy = starty[turmitecounter % 4];
_addTokenToOwnerEnumeration(mintTo, turmitecounter);
_addTokenToAllTokensEnumeration(turmitecounter);
_mint(mintTo, turmitecounter);
createTurmite(turmitecounter, uint8(startposx), uint8(startposy), 1, uint8(boardcounter), rule);
emit TurmiteMint(turmitecounter, rule, boardcounter);
if (moves > 0) {
calculateTurmiteMove(turmitecounter, moves);
}
haecceity[turmitecounter] = false;
turmitecounter = turmitecounter + 1;
}
/// @dev overwrites the tokenURI function from ERC721 Solmate
/// @param id the id of the NFT
function tokenURI(uint256 id) public view override returns (string memory) {
return
fullMetadata(
id,
turmites[id].boardnumber,
turmites[id].rule,
turmites[id].state,
turmites[id].turposx,
turmites[id].turposy,
turmites[id].orientation
);
}
/// @dev helper Function to render board without turmites
/// @param number Board number
function renderBoard(uint8 number) public view returns (string memory) {
return getSvg(number, 0, 0, false);
}
function moveTurmite(uint256[2] calldata idmoves) external {
require(msg.sender == ownerOf(idmoves[0]), "NOT_AUTHORIZED");
if (idmoves[1] > 0) {
calculateTurmiteMove(idmoves[0], idmoves[1]);
}
}
/// @dev function to validate that an new input from user is in the "gramma" of the rules
/// @param rule a bytes12 rule - to understand the specific gramma of rules take a look at turmitev4 contract
function validateNewRule(bytes12 rule) public pure returns (bool allowed) {
//Normal Format Example: 0xff0801ff0201ff0000000001
//we dont test against direction bc direction never writes
//bool firstbit = (rule[0] == 0xFF || rule[0] == 0x00);
//bool secondbit = (rule[3] == 0xFF || rule[3] == 0x00);
bool colorfieldbit = ((rule[0] == 0xFF || rule[0] == 0x00) &&
(rule[3] == 0xFF || rule[3] == 0x00) &&
(rule[6] == 0xFF || rule[6] == 0x00) &&
(rule[9] == 0xFF || rule[9] == 0x00));
bool statebit = ((rule[2] == 0x01 || rule[2] == 0x00) &&
(rule[5] == 0x01 || rule[5] == 0x00) &&
(rule[8] == 0x01 || rule[8] == 0x00) &&
(rule[11] == 0x01 || rule[11] == 0x00));
return bool(statebit && colorfieldbit);
}
/// @notice WE EXPECT THAT YOU KNOW WHAT YOU ARE DOING BEFORE CALLING THIS FUNCTION MANUALY
/// @notice PLEASE CONSULT THE DOCUMENTATION
/// @dev function to reprogramm your turmite | DANGERZONE | if you don't use the interface consult the documentation before wasting gas
/// @param id ID of the turmite
/// @param rule a bytes12 rule - to understand the specific gramma of rules take a look at turmitev4 contract
function reprogrammTurmite(uint256 id, bytes12 rule) external {
require(msg.sender == ownerOf(id), "NOT_AUTHORIZED");
require(validateNewRule(rule) == true, "INVALID_RULE");
turmites[id].rule = rule;
emit TurmiteReprogramm(id, rule);
}
/// @dev function for the admin to set external HA Contract
/// @param _haecceityContract address of contract
function setHaecceityContract(address _haecceityContract) external {
require(msg.sender == admin, "NOT_AUTHORIZED");
haecceityContract = _haecceityContract;
}
/// @dev get the position(x and y values) and the state of the current field for a turmite (all handy encoded)
/// @param id the id of the token / turmite
function getPosField(uint256 id) public view returns (bytes memory encodedData) {
bytes32 sour;
uint8 _x;
uint8 _y;
bytes memory data = new bytes(32);
turmite storage dataTurmite = turmites[id];
assembly {
sour := sload(dataTurmite.slot)
_x := and(sour, 0xFF)
_y := and(shr(8, sour), 0xFF)
}
bytes1 stateOfField = getByte(_x, _y, (id / 4) + 1);
assembly {
mstore8(add(data, 32), _x)
mstore8(add(data, 33), _y)
mstore(add(data, 34), stateOfField)
}
return (data);
}
// _ _ _____ _ _ _____ ______ _____ __________ _ _ ______ _ _
// | | | | | __ \ /\ | \ | |/ ____| ____| __ \ |___ / __ \| \ | | ____| | | | |
// | | | | | | | | / \ | \| | | __| |__ | |__) | / / | | | \| | |__ | | | |
// | | | | | | | |/ /\ \ | . ` | | |_ | __| | _ / / /| | | | . ` | __| | | | |
// |_| |_| | |__| / ____ \| |\ | |__| | |____| | \ \ / /_| |__| | |\ | |____ |_| |_|
// (_) (_) |_____/_/ \_\_| \_|\_____|______|_| \_\/_____\____/|_| \_|______| (_) (_)
/// @notice WE EXPECT THAT YOU KNOW WHAT YOU ARE DOING BEFORE CALLING THIS FUNCTION
/// @notice PLEASE CONSULT THE DOCUMENTATION
/// @dev should be called by user to unlock external control
/// @param id the id of the token / turmite the user what to hand logic control over to external smart contract
function setHaecceityMode(uint256 id) external {
require(haecceityContract != address(0), "CONTRACT_IS_ZEROADDRESS");
require(msg.sender == ownerOf(id), "NOT_AUTHORIZED");
haecceity[id] = true;
}
/// @dev internal deocde function
/// @param data data to decode
function decode(bytes memory data)
internal
pure
returns (
uint8 x,
uint8 y,
bytes1 field
)
{
assembly {
x := mload(add(data, 1))
y := mload(add(data, 2))
field := mload(add(data, 34))
}
}
/// @notice WE EXPECT THAT YOU KNOW WHAT YOU ARE DOING BEFORE CALLING THIS FUNCTION
/// @notice PLEASE CONSULT THE DOCUMENTATION
/// @dev function should be called by external haecceity Contract which allows external control of turmites by user deployed smart contracts
/// @dev this function sets the field
/// @param id the id of the turmite
/// @param data the encoded data of the next step
function setByteHaMode(uint256 id, bytes calldata data) external {
require(haecceityContract != address(0), "CONTRACT_IS_ZEROADDRESS");
require(haecceity[id] == true, "CONTRACT_NOT_INITALIZED_BY_NFT_OWNER");
require(msg.sender == haecceityContract, "CALL_ONLY_FROM_HACONTRACT");
(uint8 x, uint8 y, bytes1 stateOfField) = decode(data);
setByte(x, y, stateOfField, turmites[id].boardnumber);
}
/// @notice WE EXPECT THAT YOU KNOW WHAT YOU ARE DOING BEFORE CALLING THIS FUNCTION
/// @notice PLEASE CONSULT THE DOCUMENTATION
/// @dev function should be called by external haecceity Contract which allows external control of turmites by user deployed smart contracts
/// @dev this function sets the end position after moving
/// @param id the id of the turmite
/// @param data the encoded data of the position
function setPositionHaMode(uint256 id, bytes calldata data) external {
require(haecceityContract != address(0), "CONTRACT_IS_ZEROADDRESS");
require(haecceity[id] == true, "CONTRACT_NOT_INITALIZED_BY_NFT_OWNER");
require(msg.sender == haecceityContract, "CALL_ONLY_FROM_HACONTRACT");
(uint8 x, uint8 y, ) = decode(data);
turmites[id].turposx = x;
turmites[id].turposy = y;
}
/// @dev overwriting transfer functions to add extension from here
/// @notice after every transfer we reset the permission for external control
/// @dev resets permission after every transfer
function _transferResetHAMode(uint256 tokenId) internal {
if (haecceity[tokenId] == true) {
haecceity[tokenId] = false;
}
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
_transferResetHAMode(tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
_transferResetHAMode(tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
super.safeTransferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) public virtual override {
_transferResetHAMode(tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
super.safeTransferFrom(from, to, tokenId, data);
}
}//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./turmitev4.sol";
import "solady/src/utils/LibString.sol";
/// @title Metadata
/// @notice Renders the dynamic metadata of every NFT via the Turmite v4.
/// @author @brachlandberlin / plsdlr.net
/// @dev Generates the metadata as JSON String and encodes it with base64 and data:application/json;base64,
contract Metadata is Turmite {
string private network;
constructor(string memory _network) {
network = _network;
}
/// @dev generates the dynamic metadata
/// @param tokenId the tokenId of the Turmite
/// @param boardNumber the Board Number
/// @param rule the rule of the turmite
/// @param state current state
/// @param turposx x position of the turmite
/// @param turposy y position of the turmite
/// @param orientation orientation of the turmite
function fullMetadata(
uint256 tokenId,
uint8 boardNumber,
bytes12 rule,
bytes1 state,
uint8 turposx,
uint8 turposy,
uint8 orientation
) internal view returns (string memory) {
return
string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(
abi.encodePacked(
'{"name":"',
generateName(tokenId, boardNumber),
'", "description":"',
"Onchain Mutiplayer Art",
'", "image": "',
getSvg(boardNumber, turposx, turposy, true),
'",',
'"attributes": ',
generateAttributes(boardNumber, rule, state, turposx, turposy, orientation),
"}"
)
)
)
);
}
/// @dev generates the Name of the turmite as a string
/// @param tokenId the tokenId of the Turmite
/// @param boardNumber the Board Number
function generateName(uint256 tokenId, uint8 boardNumber) internal pure returns (string memory) {
return
string(
abi.encodePacked("Turmite ", LibString.toString(tokenId), " World ", LibString.toString(boardNumber))
);
}
/// @dev generates the dynamic attributes as JSON String, for param see fullMetadata()
function generateAttributes(
uint8 boardNumber,
bytes12 rule,
bytes1 state,
uint8 turposx,
uint8 turposy,
uint8 orientation
) internal view returns (string memory) {
return
string(
abi.encodePacked(
'[{"trait_type":"World","value":"',
LibString.toString(boardNumber),
'"},',
'{"trait_type":"Rule",',
'"value":"',
bytes12ToString(rule),
'"},',
'{"trait_type":"State",',
'"value":"',
LibString.toString(uint8(state)),
'"},',
'{"trait_type":"POS X",',
'"value":"',
LibString.toString(turposx),
'"},',
'{"trait_type":"POS Y",',
'"value":"',
LibString.toString(turposy),
'"},',
'{"trait_type":"Direction",',
'"value":"',
LibString.toString(orientation),
'"},{"trait_type":"Network","value":"',
network,
'"}]'
)
);
}
/// @dev helper function to create a String from a byte12
/// @param _bytes12 the input value
function bytes12ToString(bytes12 _bytes12) internal pure returns (string memory) {
uint8 i = 0;
bytes memory bytesArray = new bytes(24);
for (i = 0; i < bytesArray.length; i++) {
uint8 _f = uint8(_bytes12[i / 2] & 0x0f);
uint8 _l = uint8(_bytes12[i / 2] >> 4);
bytesArray[i] = toByte(_l);
i = i + 1;
bytesArray[i] = toByte(_f);
}
return string(bytesArray);
}
/// @dev helper function to convert from uint8 to byte1
/// @param _uint8 the input value
function toByte(uint8 _uint8) internal pure returns (bytes1) {
if (_uint8 < 10) {
return bytes1(_uint8 + 48);
} else {
return bytes1(_uint8 + 87);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@rari-capital/solmate/src/tokens/ERC721.sol";
/// @title EnumerableMate
/// @notice slightly reduced version of ERC721Enumerable.sol - mainly optimizing the transfer function
/// @author @brachlandberlin / plsdlr.net
/// @author OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
/// @dev Comments are mostly taken over from OpenZeppelin
abstract contract EnumerableMate is ERC721 {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
constructor(string memory name, string memory s) ERC721(name, s) {}
/// getter
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
require(index < EnumerableMate.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) internal {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) internal {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) internal {
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) internal {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./gameboard.sol";
/// @title Turmite v4
/// @notice Implementation of Turmite logic for Straylight Protocoll.
/// @author @brachlandberlin / plsdlr.net
/// @dev Every Turmite rule is for simplicity represented as 12 Bytes. For easy acess by render functions all individual turmite data is safed in an struct.
contract Turmite is Gameboard {
// using Base64 for string; //note what is this used for?
mapping(uint256 => turmite) public turmites;
event TurmiteMove(uint256 indexed tokenId, uint8 indexed boardnumber, uint256 indexed moves);
/// @dev individual slot for every turmite
// Layout from Example:
// _____________________________________________________________________________________________________
// Empty Space :) Rule State Boardnumber Orientation Y X
// _____________________________________________________________________________________________________
// 0x000000000000000000000000000000 ff0801ff0201ff0000000001 01 01 01 32 3a
// _____________________________________________________________________________________________________
//
struct turmite {
uint8 turposx;
uint8 turposy;
uint8 orientation;
uint8 boardnumber;
bytes1 state;
bytes12 rule;
}
/// @dev grammar for the rules
// Layout from example rule
// Rule:
// _________________________________________________
// ff0801ff0201ff0000000001 2 states / 4 rulessegments
// _________________________________________________
// | ff0801 | ff0201 | ff0000 | 000001 | 4 * 3 Bytes
// _________________________________________________
// | c d s | c d s | ... c = color, d = direction, s = state
// _________________________________________________
// | c = ff , d = 08 , s = 01 | ...
// _________________________________________________
//
// written as context-sensitive grammar, with start symbol S:
//
// S → a a a
// a → c d s
// c → ff | 00
// d → 02 | 08 | 04
// s → 01 | 00
/// @dev creates an Turmite Struct and mapping to id, every turmite gets initalized with state 0
/// @param posx the x position of the turmite on the board
/// @param posy the y position on the turmite on the board
/// @param startdirection the startdirection of the turmite
/// @param boardNumber the boardNumber number
/// @param rule 12 Byte rule which defines behavior of the turmite
function createTurmite(
uint256 id,
uint8 posx,
uint8 posy,
uint8 startdirection,
uint8 boardNumber,
bytes12 rule
) internal {
bytes1 state = hex"00";
turmites[id] = turmite(posx, posy, startdirection, boardNumber, state, rule);
}
/// @dev main computational logic of turmite
/// @dev this function is internal because there should be a check to validate ownership of the turmite
/// @param id the id of the turmite to move
/// @param moves the number of moves
function calculateTurmiteMove(uint256 id, uint256 moves) internal {
bytes1 colorField;
uint8 _x;
uint8 _y;
uint8 _boardNumber;
bytes32 sour;
turmite storage data = turmites[id];
assembly {
sour := sload(data.slot)
}
for (uint256 z = 0; z < moves; ) {
assembly {
_x := and(sour, 0xFF)
_y := and(shr(8, sour), 0xFF)
_boardNumber := shr(24, sour)
}
bytes1 stateOfField = getByte(_x, _y, _boardNumber);
assembly {
let maskedRule := and(sour, 0x000000000000000000000000000000ffffffffffffffffffffffff0000000000)
let _orientation := and(
shr(16, sour),
0x00000000000000000000000000000000000000000000000000000000000000ff
)
let newState
let newDirection
if and(
eq(shr(248, stateOfField), 0x00),
eq(shr(32, and(sour, 0x000000000000000000000000000000000000000000000000000000ff00000000)), 0x00)
) {
colorField := shl(120, maskedRule)
newDirection := and(shr(120, maskedRule), 0xFF)
newState := and(shr(112, maskedRule), 0xFF)
}
if and(
eq(shr(248, stateOfField), 0xff),
eq(shr(32, and(sour, 0x000000000000000000000000000000000000000000000000000000ff00000000)), 0x00)
) {
colorField := shl(144, maskedRule)
newDirection := and(shr(96, maskedRule), 0xFF)
newState := and(shr(88, maskedRule), 0xFF)
}
if and(
eq(shr(248, stateOfField), 0x00),
eq(shr(32, and(sour, 0x000000000000000000000000000000000000000000000000000000ff00000000)), 0x01)
) {
colorField := shl(168, maskedRule)
newDirection := and(shr(72, maskedRule), 0xFF)
newState := and(shr(64, maskedRule), 0xFF)
}
if and(
eq(shr(248, stateOfField), 0xff),
eq(shr(32, and(sour, 0x000000000000000000000000000000000000000000000000000000ff00000000)), 0x01)
) {
colorField := shl(192, maskedRule)
newDirection := and(shr(48, maskedRule), 0xFF)
newState := and(shr(40, maskedRule), 0xFF)
}
let newOrientation
switch newDirection
case 0x02 {
newOrientation := addmod(_orientation, 1, 4)
}
case 0x08 {
switch _orientation
case 0 {
newOrientation := 3
}
default {
newOrientation := mod(sub(_orientation, 1), 4)
}
}
case 0x04 {
newOrientation := mod(add(_orientation, 2), 4)
}
default {
newOrientation := _orientation
}
let buffer := mload(0x40)
switch newOrientation
case 0x00 {
mstore8(add(buffer, 31), addmod(_x, 1, 144))
mstore8(add(buffer, 30), _y)
}
case 0x02 {
switch _x
case 0 {
mstore8(add(buffer, 31), 143)
mstore8(add(buffer, 30), _y)
}
default {
mstore8(add(buffer, 31), sub(_x, 1))
mstore8(add(buffer, 30), _y)
}
}
case 0x03 {
mstore8(add(buffer, 31), _x)
mstore8(add(buffer, 30), addmod(_y, 1, 144))
}
case 0x01 {
switch _y
case 0 {
mstore8(add(buffer, 31), _x)
mstore8(add(buffer, 30), 143)
}
default {
mstore8(add(buffer, 31), _x)
mstore8(add(buffer, 30), sub(_y, 1))
}
}
// 128 120 112 104 96 88 80 72 64 56 48 40
// 0xff 08 01 ff 02 01 ff 00 00 00 44 21
mstore8(add(buffer, 29), newOrientation)
mstore8(add(buffer, 28), _boardNumber)
mstore8(add(buffer, 27), newState)
sour := or(mload(buffer), maskedRule)
}
// note that we pass here the "old" x & y
setByte(_x, _y, colorField, _boardNumber);
unchecked {
z += 1;
}
}
assembly {
sstore(data.slot, sour)
}
emit TurmiteMove(id, _boardNumber, moves);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
library LibString {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `length` of the output is too small to contain all the hex digits.
error HexLengthInsufficient();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The constant returned when the `search` is not found in the string.
uint256 internal constant NOT_FOUND = type(uint256).max;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DECIMAL OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the base 10 decimal representation of `value`.
function toString(uint256 value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but
// we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
// We will need 1 word for the trailing zeros padding, 1 word for the length,
// and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
let m := add(mload(0x40), 0xa0)
// Update the free memory pointer to allocate.
mstore(0x40, m)
// Assign the `str` to the end.
str := sub(m, 0x20)
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end of the memory to calculate the length later.
let end := str
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let temp := value } 1 {} {
str := sub(str, 1)
// Write the character to the pointer.
// The ASCII index of the '0' character is 48.
mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp := div(temp, 10)
// prettier-ignore
if iszero(temp) { break }
}
let length := sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str := sub(str, 0x20)
// Store the length.
mstore(str, length)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HEXADECIMAL OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the hexadecimal representation of `value`,
/// left-padded to an input length of `length` bytes.
/// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
/// giving a total length of `length * 2 + 2` bytes.
/// Reverts if `length` is too small for the output to contain all the digits.
function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value, length);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`,
/// left-padded to an input length of `length` bytes.
/// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
/// giving a total length of `length * 2` bytes.
/// Reverts if `length` is too small for the output to contain all the digits.
function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
let start := mload(0x40)
// We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
// for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
// We add 0x20 to the total and round down to a multiple of 0x20.
// (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
let m := add(start, and(add(shl(1, length), 0x62), not(0x1f)))
// Allocate the memory.
mstore(0x40, m)
// Assign the `str` to the end.
str := sub(m, 0x20)
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end to calculate the length later.
let end := str
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
let temp := value
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for {} 1 {} {
str := sub(str, 2)
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
length := sub(length, 1)
// prettier-ignore
if iszero(length) { break }
}
if temp {
// Store the function selector of `HexLengthInsufficient()`.
mstore(0x00, 0x2194895a)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Compute the string's length.
let strLength := sub(end, str)
// Move the pointer and write the length.
str := sub(str, 0x20)
mstore(str, strLength)
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
/// As address are 20 bytes long, the output will left-padded to have
/// a length of `20 * 2 + 2` bytes.
function toHexString(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is encoded using 2 hexadecimal digits per byte.
/// As address are 20 bytes long, the output will left-padded to have
/// a length of `20 * 2` bytes.
function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
let start := mload(0x40)
// We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
// 0x02 bytes for the prefix, and 0x40 bytes for the digits.
// The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
let m := add(start, 0xa0)
// Allocate the memory.
mstore(0x40, m)
// Assign the `str` to the end.
str := sub(m, 0x20)
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end to calculate the length later.
let end := str
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let temp := value } 1 {} {
str := sub(str, 2)
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
// prettier-ignore
if iszero(temp) { break }
}
// Compute the string's length.
let strLength := sub(end, str)
// Move the pointer and write the length.
str := sub(str, 0x20)
mstore(str, strLength)
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
/// and the alphabets are capitalized conditionally according to
/// https://eips.ethereum.org/EIPS/eip-55
function toHexStringChecksumed(address value) internal pure returns (string memory str) {
str = toHexString(value);
/// @solidity memory-safe-assembly
assembly {
let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
let o := add(str, 0x22)
let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
let t := shl(240, 136) // `0b10001000 << 240`
// prettier-ignore
for { let i := 0 } 1 {} {
mstore(add(i, i), mul(t, byte(i, hashed)))
i := add(i, 1)
// prettier-ignore
if eq(i, 20) { break }
}
mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
o := add(o, 0x20)
mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
function toHexString(address value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
str := mload(0x40)
// Allocate the memory.
// We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
// 0x02 bytes for the prefix, and 0x28 bytes for the digits.
// The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
mstore(0x40, add(str, 0x80))
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
str := add(str, 2)
mstore(str, 40)
let o := add(str, 0x20)
mstore(add(o, 40), 0)
value := shl(96, value)
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let i := 0 } 1 {} {
let p := add(o, add(i, i))
let temp := byte(i, value)
mstore8(add(p, 1), mload(and(temp, 15)))
mstore8(p, mload(shr(4, temp)))
i := add(i, 1)
// prettier-ignore
if eq(i, 20) { break }
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RUNE STRING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the number of UTF characters in the string.
function runeCount(string memory s) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
if mload(s) {
mstore(0x00, div(not(0), 255))
mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
let o := add(s, 0x20)
let end := add(o, mload(s))
// prettier-ignore
for { result := 1 } 1 { result := add(result, 1) } {
o := add(o, byte(0, mload(shr(250, mload(o)))))
// prettier-ignore
if iszero(lt(o, end)) { break }
}
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTE STRING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// For performance and bytecode compactness, all indices of the following operations
// are byte (ASCII) offsets, not UTF character offsets.
/// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
function replace(
string memory subject,
string memory search,
string memory replacement
) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
let replacementLength := mload(replacement)
subject := add(subject, 0x20)
search := add(search, 0x20)
replacement := add(replacement, 0x20)
result := add(mload(0x40), 0x20)
let subjectEnd := add(subject, subjectLength)
if iszero(gt(searchLength, subjectLength)) {
let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
let h := 0
if iszero(lt(searchLength, 32)) {
h := keccak256(search, searchLength)
}
let m := shl(3, sub(32, and(searchLength, 31)))
let s := mload(search)
// prettier-ignore
for {} 1 {} {
let t := mload(subject)
// Whether the first `searchLength % 32` bytes of
// `subject` and `search` matches.
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
// Copy the `replacement` one word at a time.
// prettier-ignore
for { let o := 0 } 1 {} {
mstore(add(result, o), mload(add(replacement, o)))
o := add(o, 0x20)
// prettier-ignore
if iszero(lt(o, replacementLength)) { break }
}
result := add(result, replacementLength)
subject := add(subject, searchLength)
if searchLength {
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
}
}
let resultRemainder := result
result := add(mload(0x40), 0x20)
let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
// Copy the rest of the string one word at a time.
// prettier-ignore
for {} lt(subject, subjectEnd) {} {
mstore(resultRemainder, mload(subject))
resultRemainder := add(resultRemainder, 0x20)
subject := add(subject, 0x20)
}
result := sub(result, 0x20)
// Zeroize the slot after the string.
let last := add(add(result, 0x20), k)
mstore(last, 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 31), not(31)))
// Store the length of the result.
mstore(result, k)
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from left to right, starting from `from`.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function indexOf(
string memory subject,
string memory search,
uint256 from
) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
// prettier-ignore
for { let subjectLength := mload(subject) } 1 {} {
if iszero(mload(search)) {
// `result = min(from, subjectLength)`.
result := xor(from, mul(xor(from, subjectLength), lt(subjectLength, from)))
break
}
let searchLength := mload(search)
let subjectStart := add(subject, 0x20)
result := not(0) // Initialize to `NOT_FOUND`.
subject := add(subjectStart, from)
let subjectSearchEnd := add(sub(add(subjectStart, subjectLength), searchLength), 1)
let m := shl(3, sub(32, and(searchLength, 31)))
let s := mload(add(search, 0x20))
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
if iszero(lt(searchLength, 32)) {
// prettier-ignore
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, subjectStart)
break
}
}
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
}
break
}
// prettier-ignore
for {} 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
result := sub(subject, subjectStart)
break
}
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
}
break
}
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from left to right.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) {
result = indexOf(subject, search, 0);
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from right to left, starting from `from`.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function lastIndexOf(
string memory subject,
string memory search,
uint256 from
) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
// prettier-ignore
for {} 1 {} {
let searchLength := mload(search)
let fromMax := sub(mload(subject), searchLength)
if iszero(gt(fromMax, from)) {
from := fromMax
}
if iszero(mload(search)) {
result := from
break
}
result := not(0) // Initialize to `NOT_FOUND`.
let subjectSearchEnd := sub(add(subject, 0x20), 1)
subject := add(add(subject, 0x20), from)
// prettier-ignore
if iszero(gt(subject, subjectSearchEnd)) { break }
// As this function is not too often used,
// we shall simply use keccak256 for smaller bytecode size.
// prettier-ignore
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, add(subjectSearchEnd, 1))
break
}
subject := sub(subject, 1)
// prettier-ignore
if iszero(gt(subject, subjectSearchEnd)) { break }
}
break
}
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from right to left.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) {
result = lastIndexOf(subject, search, uint256(int256(-1)));
}
/// @dev Returns whether `subject` starts with `search`.
function startsWith(string memory subject, string memory search) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
let searchLength := mload(search)
// Just using keccak256 directly is actually cheaper.
result := and(
iszero(gt(searchLength, mload(subject))),
eq(keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength))
)
}
}
/// @dev Returns whether `subject` ends with `search`.
function endsWith(string memory subject, string memory search) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
let searchLength := mload(search)
let subjectLength := mload(subject)
// Whether `search` is not longer than `subject`.
let withinRange := iszero(gt(searchLength, subjectLength))
// Just using keccak256 directly is actually cheaper.
result := and(
withinRange,
eq(
keccak256(
// `subject + 0x20 + max(subjectLength - searchLength, 0)`.
add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
searchLength
),
keccak256(add(search, 0x20), searchLength)
)
)
}
}
/// @dev Returns `subject` repeated `times`.
function repeat(string memory subject, uint256 times) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
if iszero(or(iszero(times), iszero(subjectLength))) {
subject := add(subject, 0x20)
result := mload(0x40)
let output := add(result, 0x20)
// prettier-ignore
for {} 1 {} {
// Copy the `subject` one word at a time.
// prettier-ignore
for { let o := 0 } 1 {} {
mstore(add(output, o), mload(add(subject, o)))
o := add(o, 0x20)
// prettier-ignore
if iszero(lt(o, subjectLength)) { break }
}
output := add(output, subjectLength)
times := sub(times, 1)
// prettier-ignore
if iszero(times) { break }
}
// Zeroize the slot after the string.
mstore(output, 0)
// Store the length.
let resultLength := sub(output, add(result, 0x20))
mstore(result, resultLength)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, add(result, and(add(resultLength, 63), not(31))))
}
}
}
/// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function slice(
string memory subject,
uint256 start,
uint256 end
) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
if iszero(gt(subjectLength, end)) {
end := subjectLength
}
if iszero(gt(subjectLength, start)) {
start := subjectLength
}
if lt(start, end) {
result := mload(0x40)
let resultLength := sub(end, start)
mstore(result, resultLength)
subject := add(subject, start)
let w := not(31)
// Copy the `subject` one word at a time, backwards.
// prettier-ignore
for { let o := and(add(resultLength, 31), w) } 1 {} {
mstore(add(result, o), mload(add(subject, o)))
o := add(o, w) // `sub(o, 0x20)`.
// prettier-ignore
if iszero(o) { break }
}
// Zeroize the slot after the string.
mstore(add(add(result, 0x20), resultLength), 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, add(result, and(add(resultLength, 63), w)))
}
}
}
/// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
/// `start` is a byte offset.
function slice(string memory subject, uint256 start) internal pure returns (string memory result) {
result = slice(subject, start, uint256(int256(-1)));
}
/// @dev Returns all the indices of `search` in `subject`.
/// The indices are byte offsets.
function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) {
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
if iszero(gt(searchLength, subjectLength)) {
subject := add(subject, 0x20)
search := add(search, 0x20)
result := add(mload(0x40), 0x20)
let subjectStart := subject
let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
let h := 0
if iszero(lt(searchLength, 32)) {
h := keccak256(search, searchLength)
}
let m := shl(3, sub(32, and(searchLength, 31)))
let s := mload(search)
// prettier-ignore
for {} 1 {} {
let t := mload(subject)
// Whether the first `searchLength % 32` bytes of
// `subject` and `search` matches.
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
// Append to `result`.
mstore(result, sub(subject, subjectStart))
result := add(result, 0x20)
// Advance `subject` by `searchLength`.
subject := add(subject, searchLength)
if searchLength {
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
subject := add(subject, 1)
// prettier-ignore
if iszero(lt(subject, subjectSearchEnd)) { break }
}
let resultEnd := result
// Assign `result` to the free memory pointer.
result := mload(0x40)
// Store the length of `result`.
mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
// Allocate memory for result.
// We allocate one more word, so this array can be recycled for {split}.
mstore(0x40, add(resultEnd, 0x20))
}
}
}
/// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) {
uint256[] memory indices = indicesOf(subject, delimiter);
/// @solidity memory-safe-assembly
assembly {
let w := not(31)
let indexPtr := add(indices, 0x20)
let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
mstore(add(indicesEnd, w), mload(subject))
mstore(indices, add(mload(indices), 1))
let prevIndex := 0
// prettier-ignore
for {} 1 {} {
let index := mload(indexPtr)
mstore(indexPtr, 0x60)
if iszero(eq(index, prevIndex)) {
let element := mload(0x40)
let elementLength := sub(index, prevIndex)
mstore(element, elementLength)
// Copy the `subject` one word at a time, backwards.
// prettier-ignore
for { let o := and(add(elementLength, 31), w) } 1 {} {
mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
o := add(o, w) // `sub(o, 0x20)`.
// prettier-ignore
if iszero(o) { break }
}
// Zeroize the slot after the string.
mstore(add(add(element, 0x20), elementLength), 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, add(element, and(add(elementLength, 63), w)))
// Store the `element` into the array.
mstore(indexPtr, element)
}
prevIndex := add(index, mload(delimiter))
indexPtr := add(indexPtr, 0x20)
// prettier-ignore
if iszero(lt(indexPtr, indicesEnd)) { break }
}
result := indices
if iszero(mload(delimiter)) {
result := add(indices, 0x20)
mstore(result, sub(mload(indices), 2))
}
}
}
/// @dev Returns a concatenated string of `a` and `b`.
/// Cheaper than `string.concat()` and does not de-align the free memory pointer.
function concat(string memory a, string memory b) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let w := not(31)
result := mload(0x40)
let aLength := mload(a)
// Copy `a` one word at a time, backwards.
// prettier-ignore
for { let o := and(add(mload(a), 32), w) } 1 {} {
mstore(add(result, o), mload(add(a, o)))
o := add(o, w) // `sub(o, 0x20)`.
// prettier-ignore
if iszero(o) { break }
}
let bLength := mload(b)
let output := add(result, mload(a))
// Copy `b` one word at a time, backwards.
// prettier-ignore
for { let o := and(add(bLength, 32), w) } 1 {} {
mstore(add(output, o), mload(add(b, o)))
o := add(o, w) // `sub(o, 0x20)`.
// prettier-ignore
if iszero(o) { break }
}
let totalLength := add(aLength, bLength)
let last := add(add(result, 0x20), totalLength)
// Zeroize the slot after the string.
mstore(last, 0)
// Stores the length.
mstore(result, totalLength)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 31), w))
}
}
/// @dev Returns a copy of the string in either lowercase or UPPERCASE.
function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let length := mload(subject)
if length {
result := add(mload(0x40), 0x20)
subject := add(subject, 1)
let flags := shl(add(70, shl(5, toUpper)), 67108863)
let w := not(0)
// prettier-ignore
for { let o := length } 1 {} {
o := add(o, w)
let b := and(0xff, mload(add(subject, o)))
mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
// prettier-ignore
if iszero(o) { break }
}
// Restore the result.
result := mload(0x40)
// Stores the string length.
mstore(result, length)
// Zeroize the slot after the string.
let last := add(add(result, 0x20), length)
mstore(last, 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 31), not(31)))
}
}
}
/// @dev Returns a lowercased copy of the string.
function lower(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, false);
}
/// @dev Returns an UPPERCASED copy of the string.
function upper(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, true);
}
/// @dev Escapes the string to be used within HTML tags.
function escapeHTML(string memory s) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
// prettier-ignore
for {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
// Store the bytes of the packed offsets and strides into the scratch space.
// `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
mstore(0x1f, 0x900094)
mstore(0x08, 0xc0000000a6ab)
// Store ""&'<>" into the scratch space.
mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
// Not in `["\"","'","&","<",">"]`.
if iszero(and(shl(c, 1), 0x500000c400000000)) {
mstore8(result, c)
result := add(result, 1)
continue
}
let t := shr(248, mload(c))
mstore(result, mload(and(t, 31)))
result := add(result, shr(5, t))
}
let last := result
// Zeroize the slot after the string.
mstore(last, 0)
// Restore the result to the start of the free memory.
result := mload(0x40)
// Store the length of the result.
mstore(result, sub(last, add(result, 0x20)))
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 31), not(31)))
}
}
/// @dev Escapes the string to be used within double-quotes in a JSON.
function escapeJSON(string memory s) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
// prettier-ignore
for {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
// Store "\\u0000" in scratch space.
// Store "0123456789abcdef" in scratch space.
// Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
// into the scratch space.
mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
// Bitmask for detecting `["\"","\\"]`.
let e := or(shl(0x22, 1), shl(0x5c, 1))
} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
if iszero(lt(c, 0x20)) {
if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`.
mstore8(result, c)
result := add(result, 1)
continue
}
mstore8(result, 0x5c) // "\\".
mstore8(add(result, 1), c)
result := add(result, 2)
continue
}
if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`.
mstore8(0x1d, mload(shr(4, c))) // Hex value.
mstore8(0x1e, mload(and(c, 15))) // Hex value.
mstore(result, mload(0x19)) // "\\u00XX".
result := add(result, 6)
continue
}
mstore8(result, 0x5c) // "\\".
mstore8(add(result, 1), mload(add(c, 8)))
result := add(result, 2)
}
let last := result
// Zeroize the slot after the string.
mstore(last, 0)
// Restore the result to the start of the free memory.
result := mload(0x40)
// Store the length of the result.
mstore(result, sub(last, add(result, 0x20)))
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 31), not(31)))
}
}
/// @dev Returns whether `a` equals `b`.
function eq(string memory a, string memory b) internal pure returns (bool result) {
assembly {
result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
}
}
/// @dev Packs a single string with its length into a single word.
/// Returns `bytes32(0)` if the length is zero or greater than 31.
function packOne(string memory a) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
// We don't need to zero right pad the string,
// since this is our own custom non-standard packing scheme.
result := mul(
// Load the length and the bytes.
mload(add(a, 0x1f)),
// `length != 0 && length < 32`. Abuses underflow.
// Assumes that the length is valid and within the block gas limit.
lt(sub(mload(a), 1), 0x1f)
)
}
}
/// @dev Unpacks a string packed using {packOne}.
/// Returns the empty string if `packed` is `bytes32(0)`.
/// If `packed` is not an output of {packOne}, the output behaviour is undefined.
function unpackOne(bytes32 packed) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
// Grab the free memory pointer.
result := mload(0x40)
// Allocate 2 words (1 for the length, 1 for the bytes).
mstore(0x40, add(result, 0x40))
// Zeroize the length slot.
mstore(result, 0)
// Store the length and bytes.
mstore(add(result, 0x1f), packed)
// Right pad with zeroes.
mstore(add(add(result, 0x20), mload(result)), 0)
}
}
/// @dev Packs two strings with their lengths into a single word.
/// Returns `bytes32(0)` if combined length is zero or greater than 30.
function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let aLength := mload(a)
// We don't need to zero right pad the strings,
// since this is our own custom non-standard packing scheme.
result := mul(
// Load the length and the bytes of `a` and `b`.
or(shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength))),
// `totalLength != 0 && totalLength < 31`. Abuses underflow.
// Assumes that the lengths are valid and within the block gas limit.
lt(sub(add(aLength, mload(b)), 1), 0x1e)
)
}
}
/// @dev Unpacks strings packed using {packTwo}.
/// Returns the empty strings if `packed` is `bytes32(0)`.
/// If `packed` is not an output of {packTwo}, the output behaviour is undefined.
function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) {
/// @solidity memory-safe-assembly
assembly {
// Grab the free memory pointer.
resultA := mload(0x40)
resultB := add(resultA, 0x40)
// Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
mstore(0x40, add(resultB, 0x40))
// Zeroize the length slots.
mstore(resultA, 0)
mstore(resultB, 0)
// Store the lengths and bytes.
mstore(add(resultA, 0x1f), packed)
mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
// Right pad with zeroes.
mstore(add(add(resultA, 0x20), mload(resultA)), 0)
mstore(add(add(resultB, 0x20), mload(resultB)), 0)
}
}
/// @dev Directly returns `a` without copying.
function directReturn(string memory a) internal pure {
assembly {
// Assumes that the string does not start from the scratch space.
let retStart := sub(a, 0x20)
let retSize := add(mload(a), 0x40)
// Right pad with zeroes. Just in case the string is produced
// by a method that doesn't zero right pad.
mstore(add(retStart, retSize), 0)
// Store the return offset.
mstore(retStart, 0x20)
// End the transaction, returning the string.
return(retStart, retSize)
}
}
}//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "solidity-bytes-utils/contracts/BytesLib.sol";
import "base64-sol/base64.sol";
/// @title Gameboard for inchain turmites
/// @notice Implementation of an Gameboard for Straylight Protocoll.
/// @notice we are all standing on the shoulders of giants - this board is inspired by how CryptoGhost is drawing boards
/// @author @brachlandberlin / plsdlr.net
/// @dev bytesLib & base64 are required for formating
contract Gameboard {
using BytesLib for bytes;
mapping(uint256 => gameboard) gameboards;
struct gameboard {
bytes1[144][144] board;
}
/// @dev an explicit function to get a byte with x,y,board
/// @param x the x position on the board
/// @param y the y position on the board
/// @param boardNumber the boardNumber number
function getByte(
uint256 x,
uint256 y,
uint256 boardNumber
) public view returns (bytes1) {
return gameboards[boardNumber].board[x][y];
}
/// @dev an explicit function to set a byte with x,y,value,board
/// @param x the x position on the board
/// @param y the y position on the board
/// @param value the byte1 value to set
/// @param boardNumber the board number
function setByte(
uint256 x,
uint256 y,
bytes1 value,
uint256 boardNumber
) internal {
gameboards[boardNumber].board[x][y] = value;
}
/// @dev function to generate the Bitmap Base64 encoded with boardNumber, position x, position y and boolean if turmite should be rendered
/// @param boardNumber the board number
/// @param posx the x position of the turmite on the board
/// @param posy the y position on the turmite on the board
/// @param renderTurmite boolean to render turmite
function getBitmapBase64(
uint8 boardNumber,
uint8 posx,
uint8 posy,
bool renderTurmite
) public view returns (string memory) {
return
string(
abi.encodePacked(
"data:image/bmp;base64,",
Base64.encode(getBitmap(boardNumber, posx, posy, renderTurmite))
)
);
}
/// @dev function to generate a SVG String with boardNumber, position x, position y and boolean if turmite should be rendered
/// @dev same parameters as getBitmapBase64
function getSvg(
uint8 boardNumber,
uint8 posx,
uint8 posy,
bool renderTurmite
) public view returns (string memory) {
return
string(
abi.encodePacked(
"data:image/svg+xml;base64,",
Base64.encode(
abi.encodePacked(
'<svg class="svgBGG" xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500"><defs id="someDefs"><style id="style1999"> .svgBGG { width: 500px;height: 500px;background-image: url(',
getBitmapBase64(boardNumber, posx, posy, renderTurmite),
"); background-repeat: no-repeat; background-size: 100%; image-rendering: -webkit-optimize-contrast; -ms-interpolation-mode: nearest-neighbor; image-rendering: -moz-crisp-edges; image-rendering: pixelated;}</style></defs></svg>"
)
)
)
);
}
/// @dev function to generate byte representation of the Board, position x, position y and boolean if turmite should be rendered
/// @dev BMP Header is generated externaly
/// @dev same parameters as getBitmapBase64
function getBitmap(
uint8 boardNumber,
uint8 posx,
uint8 posy,
bool renderTurmite
) public view returns (bytes memory) {
bytes
memory headers = hex"424D385500000000000036040000280000009000000090000000010008000000000002510000120B0000120B00000000000000000000000000000101010002020200030303000404040005050500060606000707070008080800090909000A0A0A000B0B0B000C0C0C000D0D0D000E0E0E000F0F0F00101010001111110012121200131313001414140015151500161616001717170018181800191919001A1A1A001B1B1B001C1C1C001D1D1D001E1E1E001F1F1F00202020002121210022222200232323002424240025252500262626002727270028282800292929002A2A2A002B2B2B002C2C2C002D2D2D002E2E2E002F2F2F00303030003131310032323200333333003434340035353500363636003737370038383800393939003A3A3A003B3B3B003C3C3C003D3D3D003E3E3E003F3F3F00404040004141410042424200434343004444440045454500464646004747470048484800494949004A4A4A004B4B4B004C4C4C004D4D4D004E4E4E004F4F4F00505050005151510052525200535353005454540055555500565656005757570058585800595959005A5A5A005B5B5B005C5C5C005D5D5D005E5E5E005F5F5F00606060006161610062626200636363006464640065656500666666006767670068686800696969006A6A6A006B6B6B006C6C6C006D6D6D006E6E6E006F6F6F00707070007171710072727200737373007474740075757500767676007777770078787800797979007A7A7A007B7B7B007C7C7C007D7D7D007E7E7E007F7F7F00808080008181810082828200838383008484840085858500868686008787870088888800898989008A8A8A008B8B8B008C8C8C008D8D8D008E8E8E008F8F8F00909090009191910092929200939393009494940095959500969696009797970098989800999999009A9A9A009B9B9B009C9C9C009D9D9D009E9E9E009F9F9F00A0A0A000A1A1A100A2A2A200A3A3A300A4A4A400A5A5A500A6A6A600A7A7A700A8A8A800A9A9A900AAAAAA00ABABAB00ACACAC00ADADAD00AEAEAE00AFAFAF00B0B0B000B1B1B100B2B2B200B3B3B300B4B4B400B5B5B500B6B6B600B7B7B700B8B8B800B9B9B900BABABA00BBBBBB00BCBCBC00BDBDBD00BEBEBE00BFBFBF00C0C0C000C1C1C100C2C2C200C3C3C300C4C4C400C5C5C500C6C6C600C7C7C700C8C8C800C9C9C900CACACA00CBCBCB00CCCCCC00CDCDCD00CECECE00CFCFCF00D0D0D000D1D1D100D2D2D200D3D3D300D4D4D400D5D5D500D6D6D600D7D7D700D8D8D800D9D9D900DADADA00DBDBDB00DCDCDC00DDDDDD00DEDEDE00DFDFDF00E0E0E000E1E1E100E2E2E200E3E3E300E4E4E400E5E5E500E6E6E600E7E7E700E8E8E800E9E9E900EAEAEA00EBEBEB00ECECEC00EDEDED00EEEEEE00EFEFEF00F0F0F000F1F1F100F2F2F200F3F3F300F4F4F400F5F5F500F6F6F600F7F7F700F8F8F800F9F9F900FAFAFA00FBFBFB00FCFCFC00FDFDFD00FEFEFE00FFFFFF00";
bytes memory returngameboard = new bytes(20736);
for (uint256 xFill = 0; xFill < 144; ++xFill) {
for (uint256 yFill = 0; yFill < 144; ++yFill) {
uint256 index = xFill + 144 * yFill;
returngameboard[index] = gameboards[boardNumber].board[xFill][yFill];
}
}
if (renderTurmite == true) {
uint256 index2 = uint256(posx) + 144 * uint256(posy);
returngameboard[index2] = bytes1(uint8(165));
}
return headers.concat(returngameboard);
}
}// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /// @title Base64 /// @author Brecht Devos - <[email protected]> /// @notice Provides functions for encoding/decoding base64 library Base64 { string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000" hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000" hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000" hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"; function encode(bytes memory data) internal pure returns (string memory) { if (data.length == 0) return ''; // load the table into memory string memory table = TABLE_ENCODE; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((data.length + 2) / 3); // add some extra buffer at the end required for the writing string memory result = new string(encodedLen + 32); assembly { // set the actual output length mstore(result, encodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 3 bytes at a time for {} lt(dataPtr, endPtr) {} { // read 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // write 4 characters mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F)))) resultPtr := add(resultPtr, 1) } // padding with '=' switch mod(mload(data), 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } } return result; } function decode(string memory _data) internal pure returns (bytes memory) { bytes memory data = bytes(_data); if (data.length == 0) return new bytes(0); require(data.length % 4 == 0, "invalid base64 decoder input"); // load the table into memory bytes memory table = TABLE_DECODE; // every 4 characters represent 3 bytes uint256 decodedLen = (data.length / 4) * 3; // add some extra buffer at the end required for the writing bytes memory result = new bytes(decodedLen + 32); assembly { // padding with '=' let lastBytes := mload(add(data, mload(data))) if eq(and(lastBytes, 0xFF), 0x3d) { decodedLen := sub(decodedLen, 1) if eq(and(lastBytes, 0xFFFF), 0x3d3d) { decodedLen := sub(decodedLen, 1) } } // set the actual output length mstore(result, decodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 4 characters at a time for {} lt(dataPtr, endPtr) {} { // read 4 characters dataPtr := add(dataPtr, 4) let input := mload(dataPtr) // write 3 bytes let output := add( add( shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)), shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))), add( shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)), and(mload(add(tablePtr, and( input , 0xFF))), 0xFF) ) ) mstore(resultPtr, shl(232, output)) resultPtr := add(resultPtr, 3) } } return result; } }
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory);
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) internal _ownerOf;
mapping(address => uint256) internal _balanceOf;
function ownerOf(uint256 id) public view virtual returns (address owner) {
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
}
function balanceOf(address owner) public view virtual returns (uint256) {
require(owner != address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 id) public virtual {
address owner = _ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(
address from,
address to,
uint256 id
) public virtual {
require(from == _ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
"NOT_AUTHORIZED"
);
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
unchecked {
_balanceOf[from]--;
_balanceOf[to]++;
}
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes calldata data
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
// Counter overflow is incredibly unrealistic.
unchecked {
_balanceOf[to]++;
}
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = _ownerOf[id];
require(owner != address(0), "NOT_MINTED");
// Ownership check above ensures no underflow.
unchecked {
_balanceOf[owner]--;
}
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MINT LOGIC
//////////////////////////////////////////////////////////////*/
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(
address to,
uint256 id,
bytes memory data
) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC721TokenReceiver.onERC721Received.selector;
}
}{
"viaIR": false,
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_minterContract","type":"address"},{"internalType":"uint256","name":"maxAmount","type":"uint256"},{"internalType":"string","name":"network","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"bytes12","name":"rule","type":"bytes12"},{"indexed":false,"internalType":"uint256","name":"boardId","type":"uint256"}],"name":"TurmiteMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint8","name":"boardnumber","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"moves","type":"uint256"}],"name":"TurmiteMove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"bytes12","name":"newrule","type":"bytes12"}],"name":"TurmiteReprogramm","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boardcounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"boardNumber","type":"uint8"},{"internalType":"uint8","name":"posx","type":"uint8"},{"internalType":"uint8","name":"posy","type":"uint8"},{"internalType":"bool","name":"renderTurmite","type":"bool"}],"name":"getBitmap","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"boardNumber","type":"uint8"},{"internalType":"uint8","name":"posx","type":"uint8"},{"internalType":"uint8","name":"posy","type":"uint8"},{"internalType":"bool","name":"renderTurmite","type":"bool"}],"name":"getBitmapBase64","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"boardNumber","type":"uint256"}],"name":"getByte","outputs":[{"internalType":"bytes1","name":"","type":"bytes1"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getPosField","outputs":[{"internalType":"bytes","name":"encodedData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"boardNumber","type":"uint8"},{"internalType":"uint8","name":"posx","type":"uint8"},{"internalType":"uint8","name":"posy","type":"uint8"},{"internalType":"bool","name":"renderTurmite","type":"bool"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"haecceity","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxnumbturmites","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"idmoves","type":"uint256[2]"}],"name":"moveTurmite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"mintTo","type":"address"},{"internalType":"bytes12","name":"rule","type":"bytes12"},{"internalType":"uint256","name":"moves","type":"uint256"}],"name":"publicmint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"number","type":"uint8"}],"name":"renderBoard","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes12","name":"rule","type":"bytes12"}],"name":"reprogrammTurmite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setByteHaMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_haecceityContract","type":"address"}],"name":"setHaecceityContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"setHaecceityMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setPositionHaMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"turmites","outputs":[{"internalType":"uint8","name":"turposx","type":"uint8"},{"internalType":"uint8","name":"turposy","type":"uint8"},{"internalType":"uint8","name":"orientation","type":"uint8"},{"internalType":"uint8","name":"boardnumber","type":"uint8"},{"internalType":"bytes1","name":"state","type":"bytes1"},{"internalType":"bytes12","name":"rule","type":"bytes12"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes12","name":"rule","type":"bytes12"}],"name":"validateNewRule","outputs":[{"internalType":"bool","name":"allowed","type":"bool"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
60806040526000600d556000600e556040518060800160405280602460ff168152602001604860ff168152602001604860ff168152602001606c60ff1681525060109060046200005192919062000205565b506040518060800160405280604860ff168152602001602460ff168152602001606c60ff168152602001604860ff1681525060149060046200009592919062000205565b50348015620000a357600080fd5b506040516200678d3803806200678d8339818101604052810190620000c99190620004ab565b806040518060400160405280600a81526020017f53747261796c69676874000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f53545200000000000000000000000000000000000000000000000000000000008152508181816000908162000149919062000767565b5080600190816200015b919062000767565b505050505080600c908162000171919062000767565b505082601860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600f8190555033601a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050506200084e565b82600481019282156200023c579160200282015b828111156200023b578251829060ff1690559160200191906001019062000219565b5b5090506200024b91906200024f565b5090565b5b808211156200026a57600081600090555060010162000250565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002af8262000282565b9050919050565b620002c181620002a2565b8114620002cd57600080fd5b50565b600081519050620002e181620002b6565b92915050565b6000819050919050565b620002fc81620002e7565b81146200030857600080fd5b50565b6000815190506200031c81620002f1565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000377826200032c565b810181811067ffffffffffffffff821117156200039957620003986200033d565b5b80604052505050565b6000620003ae6200026e565b9050620003bc82826200036c565b919050565b600067ffffffffffffffff821115620003df57620003de6200033d565b5b620003ea826200032c565b9050602081019050919050565b60005b8381101562000417578082015181840152602081019050620003fa565b8381111562000427576000848401525b50505050565b6000620004446200043e84620003c1565b620003a2565b90508281526020810184848401111562000463576200046262000327565b5b62000470848285620003f7565b509392505050565b600082601f83011262000490576200048f62000322565b5b8151620004a28482602086016200042d565b91505092915050565b600080600060608486031215620004c757620004c662000278565b5b6000620004d786828701620002d0565b9350506020620004ea868287016200030b565b925050604084015167ffffffffffffffff8111156200050e576200050d6200027d565b5b6200051c8682870162000478565b9150509250925092565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200057957607f821691505b6020821081036200058f576200058e62000531565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005f97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620005ba565b620006058683620005ba565b95508019841693508086168417925050509392505050565b6000819050919050565b600062000648620006426200063c84620002e7565b6200061d565b620002e7565b9050919050565b6000819050919050565b620006648362000627565b6200067c62000673826200064f565b848454620005c7565b825550505050565b600090565b6200069362000684565b620006a081848462000659565b505050565b5b81811015620006c857620006bc60008262000689565b600181019050620006a6565b5050565b601f8211156200071757620006e18162000595565b620006ec84620005aa565b81016020851015620006fc578190505b620007146200070b85620005aa565b830182620006a5565b50505b505050565b600082821c905092915050565b60006200073c600019846008026200071c565b1980831691505092915050565b600062000757838362000729565b9150826002028217905092915050565b620007728262000526565b67ffffffffffffffff8111156200078e576200078d6200033d565b5b6200079a825462000560565b620007a7828285620006cc565b600060209050601f831160018114620007df5760008415620007ca578287015190505b620007d6858262000749565b86555062000846565b601f198416620007ef8662000595565b60005b828110156200081957848901518255600182019150602085019450602081019050620007f2565b8683101562000839578489015162000835601f89168262000729565b8355505b6001600288020188555050505b505050505050565b615f2f806200085e6000396000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c80636352211e1161011a578063c2a8d57c116100ad578063d3158b021161007c578063d3158b021461065c578063e524b3071461067a578063e8354445146106aa578063e985e9c5146106c6578063ef7af2fc146106f657610206565b8063c2a8d57c146105c4578063c61a3c84146105e0578063c87b56dd146105fc578063c966409d1461062c57610206565b806395d89b41116100e957806395d89b411461053e578063a22cb4651461055c578063b88d4fde14610578578063be76bf8f1461059457610206565b80636352211e1461049257806369dbd7d7146104c25780636c5453a6146104f257806370a082311461050e57610206565b80632cc4837f1161019d57806340cb8af91161016c57806340cb8af9146103ca57806342842e0e146103fa5780634f6ccce714610416578063518a8802146104465780635e8c32111461046257610206565b80632cc4837f146103305780632f745c591461034e57806335faee731461037e5780633aedf55c146103ae57610206565b80631034fc0d116101d95780631034fc0d146102a557806313f36fc1146102c157806318160ddd146102f657806323b872dd1461031457610206565b806301ffc9a71461020b57806306fdde031461023b578063081812fc14610259578063095ea7b314610289575b600080fd5b61022560048036038101906102209190613a09565b610726565b6040516102329190613a51565b60405180910390f35b6102436107b8565b6040516102509190613b05565b60405180910390f35b610273600480360381019061026e9190613b5d565b610846565b6040516102809190613bcb565b60405180910390f35b6102a3600480360381019061029e9190613c12565b610879565b005b6102bf60048036038101906102ba9190613caa565b610a62565b005b6102db60048036038101906102d69190613b5d565b610baa565b6040516102ed96959493929190613d50565b60405180910390f35b6102fe610c34565b60405161030b9190613dc0565b60405180910390f35b61032e60048036038101906103299190613ddb565b610c41565b005b610338610c6e565b6040516103459190613dc0565b60405180910390f35b61036860048036038101906103639190613c12565b610c74565b6040516103759190613dc0565b60405180910390f35b61039860048036038101906103939190613e2e565b610d19565b6040516103a59190613a51565b60405180910390f35b6103c860048036038101906103c39190613ec0565b61119d565b005b6103e460048036038101906103df9190613b5d565b6113bd565b6040516103f19190613a51565b60405180910390f35b610414600480360381019061040f9190613ddb565b6113dd565b005b610430600480360381019061042b9190613b5d565b61140a565b60405161043d9190613dc0565b60405180910390f35b610460600480360381019061045b9190613f20565b61147b565b005b61047c60048036038101906104779190613fa5565b61154f565b6040516104899190613b05565b60405180910390f35b6104ac60048036038101906104a79190613b5d565b61158e565b6040516104b99190613bcb565b60405180910390f35b6104dc60048036038101906104d79190613fa5565b611639565b6040516104e99190613b05565b60405180910390f35b61050c60048036038101906105079190613ec0565b611697565b005b61052860048036038101906105239190613f20565b6118d9565b6040516105359190613dc0565b60405180910390f35b610546611990565b6040516105539190613b05565b60405180910390f35b6105766004803603810190610571919061400c565b611a1e565b005b610592600480360381019061058d919061404c565b611b1b565b005b6105ae60048036038101906105a99190613fa5565b611b4c565b6040516105bb9190614129565b60405180910390f35b6105de60048036038101906105d9919061414b565b611d49565b005b6105fa60048036038101906105f59190613b5d565b611fc9565b005b61061660048036038101906106119190613b5d565b6120ff565b6040516106239190613b05565b60405180910390f35b6106466004803603810190610641919061419e565b6121e9565b6040516106539190613b05565b60405180910390f35b610664612200565b6040516106719190613dc0565b60405180910390f35b610694600480360381019061068f91906141cb565b612206565b6040516106a1919061421e565b60405180910390f35b6106c460048036038101906106bf919061425b565b612265565b005b6106e060048036038101906106db9190614288565b612352565b6040516106ed9190613a51565b60405180910390f35b610710600480360381019061070b9190613b5d565b612381565b60405161071d9190614129565b60405180910390f35b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061078157506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107b15750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600080546107c5906142f7565b80601f01602080910402602001604051908101604052809291908181526020018280546107f1906142f7565b801561083e5780601f106108135761010080835404028352916020019161083e565b820191906000526020600020905b81548152906001019060200180831161082157829003601f168201915b505050505081565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109715750600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6109b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a790614374565b60405180910390fd5b826004600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610a6b8261158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ad8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610acf90614374565b60405180910390fd5b60011515610ae582610d19565b151514610b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1e906143e0565b60405180910390fd5b80600b600084815260200190815260200160002060000160056101000a8154816bffffffffffffffffffffffff021916908360a01c02179055508073ffffffffffffffffffffffffffffffffffffffff1916827fd1464fd210d58c95f829eeb54351bb3b0f9cf4277440f5627f822489a0548cd360405160405180910390a35050565b600b6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900460f81b908060000160059054906101000a900460a01b905086565b6000600880549050905090565b610c4a81612450565b610c5483826124ac565b610c5e8282612619565b610c69838383612698565b505050565b600f5481565b6000610c7f836118d9565b8210610cc0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb790614472565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60008060ff60f81b836000600c8110610d3557610d34614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610da35750600060f81b836000600c8110610d7b57610d7a614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8015610e32575060ff60f81b836003600c8110610dc357610dc2614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610e315750600060f81b836003600c8110610e0957610e08614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b8015610ec1575060ff60f81b836006600c8110610e5257610e51614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610ec05750600060f81b836006600c8110610e9857610e97614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b8015610f50575060ff60f81b836009600c8110610ee157610ee0614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610f4f5750600060f81b836009600c8110610f2757610f26614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b90506000600160f81b846002600c8110610f6d57610f6c614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610fdb5750600060f81b846002600c8110610fb357610fb2614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b801561106a5750600160f81b846005600c8110610ffb57610ffa614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110695750600060f81b846005600c811061104157611040614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b80156110f95750600160f81b846008600c811061108a57611089614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110f85750600060f81b846008600c81106110d0576110cf614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b80156111885750600160f81b84600b600c811061111957611118614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806111875750600060f81b84600b600c811061115f5761115e614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b90508080156111945750815b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361122e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112259061450d565b60405180910390fd5b60011515601b600085815260200190815260200160002060009054906101000a900460ff16151514611295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128c9061459f565b60405180910390fd5b601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131c9061460b565b60405180910390fd5b600080600061137785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612a97565b9250925092506113b58360ff168360ff1683600b60008b815260200190815260200160002060000160039054906101000a900460ff1660ff16612ab8565b505050505050565b601b6020528060005260406000206000915054906101000a900460ff1681565b6113e681612450565b6113f083826124ac565b6113fa8282612619565b611405838383612b1d565b505050565b6000611414610c34565b8210611455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144c9061469d565b60405180910390fd5b6008828154811061146957611468614492565b5b90600052602060002001549050919050565b601a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461150b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161150290614374565b60405180910390fd5b80601960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b606061156561156086868686611b4c565b612c55565b6040516020016115759190614745565b6040516020818303038152906040529050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508173ffffffffffffffffffffffffffffffffffffffff1603611634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162b906147b3565b60405180910390fd5b919050565b606061166e61164a8686868661154f565b60405160200161165a9190614a59565b604051602081830303815290604052612c55565b60405160200161167e9190614ad2565b6040516020818303038152906040529050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611728576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161171f9061450d565b60405180910390fd5b60011515601b600085815260200190815260200160002060009054906101000a900460ff1615151461178f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117869061459f565b60405180910390fd5b601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461181f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118169061460b565b60405180910390fd5b60008061186f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612a97565b509150915081600b600087815260200190815260200160002060000160006101000a81548160ff021916908360ff16021790555080600b600087815260200190815260200160002060000160016101000a81548160ff021916908360ff1602179055505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194090614b40565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6001805461199d906142f7565b80601f01602080910402602001604051908101604052809291908181526020018280546119c9906142f7565b8015611a165780601f106119eb57610100808354040283529160200191611a16565b820191906000526020600020905b8154815290600101906020018083116119f957829003601f168201915b505050505081565b80600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b0f9190613a51565b60405180910390a35050565b611b2483612450565b611b2e85846124ac565b611b388484612619565b611b458585858585612dcd565b5050505050565b606060006040518061046001604052806104368152602001615ac461043691399050600061510067ffffffffffffffff811115611b8c57611b8b614b60565b5b6040519080825280601f01601f191660200182016040528015611bbe5781602001600182028036833780820191505090505b50905060005b6090811015611cb25760005b6090811015611ca0576000816090611be89190614bbe565b83611bf39190614c18565b9050600a60008b60ff1681526020019081526020016000206000018360908110611c2057611c1f614492565b5b600502018260908110611c3657611c35614492565b5b602091828204019190069054906101000a900460f81b848281518110611c5f57611c5e614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505080611c9990614c6e565b9050611bd0565b5080611cab90614c6e565b9050611bc4565b506001151584151503611d2a5760008560ff166090611cd19190614bbe565b8760ff16611cdf9190614c18565b905060a560f81b828281518110611cf957611cf8614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350505b611d3d8183612f0b90919063ffffffff16565b92505050949350505050565b600f54600e5410611d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8690614d02565b60405180910390fd5b60011515611d9c83610d19565b151514611dde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd5906143e0565b60405180910390fd5b601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6590614d6e565b60405180910390fd5b60016004600e54611e7f9190614dbd565b611e899190614c18565b600d81905550600060106004600e54611ea29190614dee565b60048110611eb357611eb2614492565b5b01549050600060146004600e54611eca9190614dee565b60048110611edb57611eda614492565b5b01549050611eeb85600e54612619565b611ef6600e54612f95565b611f0285600e54612fde565b611f15600e5483836001600d54896131f0565b8373ffffffffffffffffffffffffffffffffffffffff1916600e547f66e34e24596794eb9fbba61ddf385dbbc89563ac1f0250e6587c2ac6c039481d600d54604051611f619190613dc0565b60405180910390a36000831115611f7f57611f7e600e5484613354565b5b6000601b6000600e54815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600e54611fbc9190614c18565b600e819055505050505050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361205a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120519061450d565b60405180910390fd5b6120638161158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c790614374565b60405180910390fd5b6001601b600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60606121e282600b600085815260200190815260200160002060000160039054906101000a900460ff16600b600086815260200190815260200160002060000160059054906101000a900460a01b600b600087815260200190815260200160002060000160049054906101000a900460f81b600b600088815260200190815260200160002060000160009054906101000a900460ff16600b600089815260200190815260200160002060000160019054906101000a900460ff16600b60008a815260200190815260200160002060000160029054906101000a900460ff1661362c565b9050919050565b60606121f9826000806000611639565b9050919050565b600d5481565b6000600a600083815260200190815260200160002060000184609081106122305761222f614492565b5b60050201836090811061224657612245614492565b5b602091828204019190069054906101000a900460f81b90509392505050565b6122868160006002811061227c5761227b614492565b5b602002013561158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146122f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ea90614374565b60405180910390fd5b60008160016002811061230957612308614492565b5b6020020135111561234f5761234e8160006002811061232b5761232a614492565b5b60200201358260016002811061234457612343614492565b5b6020020135613354565b5b50565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6060600080600080602067ffffffffffffffff8111156123a4576123a3614b60565b5b6040519080825280601f01601f1916602001820160405280156123d65781602001600182028036833780820191505090505b5090506000600b600088815260200190815260200160002090508054945060ff8516935060ff8560081c169250600061242e8560ff168560ff16600160048c61241f9190614dbd565b6124299190614c18565b612206565b9050846020840153836021840153806022840152829650505050505050919050565b60011515601b600083815260200190815260200160002060009054906101000a900460ff161515036124a9576000601b600083815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b600060016124b9846118d9565b6124c39190614e1f565b90506000600760008481526020019081526020016000205490508181146125a8576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000612624836118d9565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273090614e9f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279f90614f0b565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806128685750600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b806128d157506004600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290790614374565b60405180910390fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600190039190505550600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008060006001840151925060028401519150602284015190509193909250565b81600a60008381526020019081526020016000206000018560908110612ae157612ae0614492565b5b600502018460908110612af757612af6614492565b5b602091828204019190066101000a81548160ff021916908360f81c021790555050505050565b612b28838383610c41565b60008273ffffffffffffffffffffffffffffffffffffffff163b1480612c11575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168273ffffffffffffffffffffffffffffffffffffffff1663150b7a023386856040518463ffffffff1660e01b8152600401612bad93929190614f51565b6020604051808303816000875af1158015612bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf09190614fb0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b612c50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c4790615029565b60405180910390fd5b505050565b60606000825103612c7757604051806020016040528060008152509050612dc8565b6000604051806060016040528060408152602001615a846040913990506000600360028551612ca69190614c18565b612cb09190614dbd565b6004612cbc9190614bbe565b90506000602082612ccd9190614c18565b67ffffffffffffffff811115612ce657612ce5614b60565b5b6040519080825280601f01601f191660200182016040528015612d185781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612d87576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612d2c565b600389510660018114612da15760028114612db157612dbc565b613d3d60f01b6002830352612dbc565b603d60f81b60018303525b50505050508093505050505b919050565b612dd8858585610c41565b60008473ffffffffffffffffffffffffffffffffffffffff163b1480612ec5575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663150b7a0233888787876040518663ffffffff1660e01b8152600401612e61959493929190615085565b6020604051808303816000875af1158015612e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea49190614fb0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b612f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612efb90615029565b60405180910390fd5b5050505050565b6060806040519050835180825260208201818101602087015b81831015612f415780518352602083019250602081019050612f24565b50855192508351830184528091508282019050602086015b81831015612f765780518352602083019250602081019050612f59565b50601f19601f8851850115830101166040525050508091505092915050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361304d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161304490614f0b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146130ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130e69061511f565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60006040518060c001604052808760ff1681526020018660ff1681526020018560ff1681526020018460ff168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020018373ffffffffffffffffffffffffffffffffffffffff1916815250600b600089815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548160ff021916908360ff16021790555060608201518160000160036101000a81548160ff021916908360ff16021790555060808201518160000160046101000a81548160ff021916908360f81c021790555060a08201518160000160056101000a8154816bffffffffffffffffffffffff021916908360a01c021790555090505050505050505050565b600080600080600080600b600089815260200190815260200160002090508054915060005b878110156135ec5760ff8316955060ff8360081c1694508260181c935060006133ac8760ff168760ff168760ff16612206565b905070ffffffffffffffffffffffff0000000000841660ff8560101c16600080600064ff00000000891660201c1460008660f81c141615613400578360781b9b5060ff8460781c16905060ff8460701c1691505b600064ff00000000891660201c1460ff8660f81c141615613434578360901b9b5060ff8460601c16905060ff8460581c1691505b600164ff00000000891660201c1460008660f81c141615613468578360a81b9b5060ff8460481c16905060ff8460401c1691505b600164ff00000000891660201c1460ff8660f81c14161561349c578360c01b9b5060ff8460301c16905060ff8460281c1691505b600081600281146134bf57600881146134cc57600481146134ee578491506134f8565b60046001860891506134f8565b84600081146134e3576004600187030692506134e8565b600392505b506134f8565b6004600286010691505b50604051816000811461352257600281146135385760038114613569576001811461357f576135ac565b609060018f08601f8301538c601e8301536135ac565b8d600081146135555760018f03601f8401538d601e840153613563565b608f601f8401538d601e8401535b506135ac565b8d601f830153609060018e08601e8301536135ac565b8c6000811461359c578e601f84015360018e03601e8401536135aa565b8e601f840153608f601e8401535b505b5081601d8201538a601c82015383601b8201538581511799505050505050506135e08760ff168760ff168a8860ff16612ab8565b60018201915050613379565b50818155868360ff16897fbbe0aa2504840f3cabeaa7c222bc975ed888abf937945ff374653c8d57c55fbb60405160405180910390a45050505050505050565b606061367c61363b89896136a8565b6136488987876001611639565b6136568a8a8a8a8a8a6136e7565b60405160200161366893929190615353565b604051602081830303815290604052612c55565b60405160200161368c919061541d565b6040516020818303038152906040529050979650505050505050565b60606136b383613764565b6136bf8360ff16613764565b6040516020016136d09291906154d7565b604051602081830303815290604052905092915050565b60606136f58760ff16613764565b6136fe876137b4565b61370d8760f81c60ff16613764565b6137198760ff16613764565b6137258760ff16613764565b6137318760ff16613764565b600c60405160200161374997969594939291906158c7565b60405160208183030381529060405290509695505050505050565b606060a060405101806040526020810391506000825281835b60011561379f57600184039350600a81066030018453600a810490508061377d575b50828103602084039350808452505050919050565b6060600080601867ffffffffffffffff8111156137d4576137d3614b60565b5b6040519080825280601f01601f1916602001820160405280156138065781602001600182028036833780820191505090505b509050600091505b80518260ff161015613960576000600f60f81b8560028561382f91906159f2565b60ff16600c811061384357613842614492565b5b1a60f81b1660f81c9050600060048660028661385f91906159f2565b60ff16600c811061387357613872614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60f81c90506138a98161396a565b838560ff16815181106138bf576138be614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001846138fb9190615a23565b93506139068261396a565b838560ff168151811061391c5761391b614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505050818061395890615a5a565b92505061380e565b8092505050919050565b6000600a8260ff16101561398f576030826139859190615a23565b60f81b90506139a2565b60578261399c9190615a23565b60f81b90505b919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6139e6816139b1565b81146139f157600080fd5b50565b600081359050613a03816139dd565b92915050565b600060208284031215613a1f57613a1e6139a7565b5b6000613a2d848285016139f4565b91505092915050565b60008115159050919050565b613a4b81613a36565b82525050565b6000602082019050613a666000830184613a42565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613aa6578082015181840152602081019050613a8b565b83811115613ab5576000848401525b50505050565b6000601f19601f8301169050919050565b6000613ad782613a6c565b613ae18185613a77565b9350613af1818560208601613a88565b613afa81613abb565b840191505092915050565b60006020820190508181036000830152613b1f8184613acc565b905092915050565b6000819050919050565b613b3a81613b27565b8114613b4557600080fd5b50565b600081359050613b5781613b31565b92915050565b600060208284031215613b7357613b726139a7565b5b6000613b8184828501613b48565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613bb582613b8a565b9050919050565b613bc581613baa565b82525050565b6000602082019050613be06000830184613bbc565b92915050565b613bef81613baa565b8114613bfa57600080fd5b50565b600081359050613c0c81613be6565b92915050565b60008060408385031215613c2957613c286139a7565b5b6000613c3785828601613bfd565b9250506020613c4885828601613b48565b9150509250929050565b60007fffffffffffffffffffffffff000000000000000000000000000000000000000082169050919050565b613c8781613c52565b8114613c9257600080fd5b50565b600081359050613ca481613c7e565b92915050565b60008060408385031215613cc157613cc06139a7565b5b6000613ccf85828601613b48565b9250506020613ce085828601613c95565b9150509250929050565b600060ff82169050919050565b613d0081613cea565b82525050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613d3b81613d06565b82525050565b613d4a81613c52565b82525050565b600060c082019050613d656000830189613cf7565b613d726020830188613cf7565b613d7f6040830187613cf7565b613d8c6060830186613cf7565b613d996080830185613d32565b613da660a0830184613d41565b979650505050505050565b613dba81613b27565b82525050565b6000602082019050613dd56000830184613db1565b92915050565b600080600060608486031215613df457613df36139a7565b5b6000613e0286828701613bfd565b9350506020613e1386828701613bfd565b9250506040613e2486828701613b48565b9150509250925092565b600060208284031215613e4457613e436139a7565b5b6000613e5284828501613c95565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613e8057613e7f613e5b565b5b8235905067ffffffffffffffff811115613e9d57613e9c613e60565b5b602083019150836001820283011115613eb957613eb8613e65565b5b9250929050565b600080600060408486031215613ed957613ed86139a7565b5b6000613ee786828701613b48565b935050602084013567ffffffffffffffff811115613f0857613f076139ac565b5b613f1486828701613e6a565b92509250509250925092565b600060208284031215613f3657613f356139a7565b5b6000613f4484828501613bfd565b91505092915050565b613f5681613cea565b8114613f6157600080fd5b50565b600081359050613f7381613f4d565b92915050565b613f8281613a36565b8114613f8d57600080fd5b50565b600081359050613f9f81613f79565b92915050565b60008060008060808587031215613fbf57613fbe6139a7565b5b6000613fcd87828801613f64565b9450506020613fde87828801613f64565b9350506040613fef87828801613f64565b925050606061400087828801613f90565b91505092959194509250565b60008060408385031215614023576140226139a7565b5b600061403185828601613bfd565b925050602061404285828601613f90565b9150509250929050565b600080600080600060808688031215614068576140676139a7565b5b600061407688828901613bfd565b955050602061408788828901613bfd565b945050604061409888828901613b48565b935050606086013567ffffffffffffffff8111156140b9576140b86139ac565b5b6140c588828901613e6a565b92509250509295509295909350565b600081519050919050565b600082825260208201905092915050565b60006140fb826140d4565b61410581856140df565b9350614115818560208601613a88565b61411e81613abb565b840191505092915050565b6000602082019050818103600083015261414381846140f0565b905092915050565b600080600060608486031215614164576141636139a7565b5b600061417286828701613bfd565b935050602061418386828701613c95565b925050604061419486828701613b48565b9150509250925092565b6000602082840312156141b4576141b36139a7565b5b60006141c284828501613f64565b91505092915050565b6000806000606084860312156141e4576141e36139a7565b5b60006141f286828701613b48565b935050602061420386828701613b48565b925050604061421486828701613b48565b9150509250925092565b60006020820190506142336000830184613d32565b92915050565b60008190508260206002028201111561425557614254613e65565b5b92915050565b600060408284031215614271576142706139a7565b5b600061427f84828501614239565b91505092915050565b6000806040838503121561429f5761429e6139a7565b5b60006142ad85828601613bfd565b92505060206142be85828601613bfd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061430f57607f821691505b602082108103614322576143216142c8565b5b50919050565b7f4e4f545f415554484f52495a4544000000000000000000000000000000000000600082015250565b600061435e600e83613a77565b915061436982614328565b602082019050919050565b6000602082019050818103600083015261438d81614351565b9050919050565b7f494e56414c49445f52554c450000000000000000000000000000000000000000600082015250565b60006143ca600c83613a77565b91506143d582614394565b602082019050919050565b600060208201905081810360008301526143f9816143bd565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b600061445c602b83613a77565b915061446782614400565b604082019050919050565b6000602082019050818103600083015261448b8161444f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f434f4e54524143545f49535f5a45524f41444452455353000000000000000000600082015250565b60006144f7601783613a77565b9150614502826144c1565b602082019050919050565b60006020820190508181036000830152614526816144ea565b9050919050565b7f434f4e54524143545f4e4f545f494e4954414c495a45445f42595f4e46545f4f60008201527f574e455200000000000000000000000000000000000000000000000000000000602082015250565b6000614589602483613a77565b91506145948261452d565b604082019050919050565b600060208201905081810360008301526145b88161457c565b9050919050565b7f43414c4c5f4f4e4c595f46524f4d5f4841434f4e545241435400000000000000600082015250565b60006145f5601983613a77565b9150614600826145bf565b602082019050919050565b60006020820190508181036000830152614624816145e8565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614687602c83613a77565b91506146928261462b565b604082019050919050565b600060208201905081810360008301526146b68161467a565b9050919050565b600081905092915050565b7f646174613a696d6167652f626d703b6261736536342c00000000000000000000600082015250565b60006146fe6016836146bd565b9150614709826146c8565b601682019050919050565b600061471f82613a6c565b61472981856146bd565b9350614739818560208601613a88565b80840191505092915050565b6000614750826146f1565b915061475c8284614714565b915081905092915050565b7f4e4f545f4d494e54454400000000000000000000000000000000000000000000600082015250565b600061479d600a83613a77565b91506147a882614767565b602082019050919050565b600060208201905081810360008301526147cc81614790565b9050919050565b7f3c73766720636c6173733d227376674247472220786d6c6e733d22687474703a60008201527f2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d2260208201527f312e31222077696474683d2235303022206865696768743d22353030223e3c6460408201527f6566732069643d22736f6d6544656673223e3c7374796c652069643d2273747960608201527f6c6531393939223e202e737667424747207b2077696474683a2035303070783b60808201527f6865696768743a2035303070783b6261636b67726f756e642d696d6167653a2060a08201527f75726c280000000000000000000000000000000000000000000000000000000060c082015250565b60006148ed60c4836146bd565b91506148f8826147d3565b60c482019050919050565b7f293b206261636b67726f756e642d7265706561743a206e6f2d7265706561743b60008201527f206261636b67726f756e642d73697a653a20313030253b20696d6167652d726560208201527f6e646572696e673a202d7765626b69742d6f7074696d697a652d636f6e74726160408201527f73743b202d6d732d696e746572706f6c6174696f6e2d6d6f64653a206e65617260608201527f6573742d6e65696768626f723b20696d6167652d72656e646572696e673a202d60808201527f6d6f7a2d63726973702d65646765733b20696d6167652d72656e646572696e6760a08201527f3a20706978656c617465643b7d3c2f7374796c653e3c2f646566733e3c2f737660c08201527f673e00000000000000000000000000000000000000000000000000000000000060e082015250565b6000614a4360e2836146bd565b9150614a4e82614903565b60e282019050919050565b6000614a64826148e0565b9150614a708284614714565b9150614a7b82614a36565b915081905092915050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000600082015250565b6000614abc601a836146bd565b9150614ac782614a86565b601a82019050919050565b6000614add82614aaf565b9150614ae98284614714565b915081905092915050565b7f5a45524f5f414444524553530000000000000000000000000000000000000000600082015250565b6000614b2a600c83613a77565b9150614b3582614af4565b602082019050919050565b60006020820190508181036000830152614b5981614b1d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614bc982613b27565b9150614bd483613b27565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c0d57614c0c614b8f565b5b828202905092915050565b6000614c2382613b27565b9150614c2e83613b27565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614c6357614c62614b8f565b5b828201905092915050565b6000614c7982613b27565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614cab57614caa614b8f565b5b600182019050919050565b7f4d494e545f4f5645520000000000000000000000000000000000000000000000600082015250565b6000614cec600983613a77565b9150614cf782614cb6565b602082019050919050565b60006020820190508181036000830152614d1b81614cdf565b9050919050565b7f4f4e4c595f4d494e5441424c455f46524f4d5f4d494e545f434f4e5452414354600082015250565b6000614d58602083613a77565b9150614d6382614d22565b602082019050919050565b60006020820190508181036000830152614d8781614d4b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614dc882613b27565b9150614dd383613b27565b925082614de357614de2614d8e565b5b828204905092915050565b6000614df982613b27565b9150614e0483613b27565b925082614e1457614e13614d8e565b5b828206905092915050565b6000614e2a82613b27565b9150614e3583613b27565b925082821015614e4857614e47614b8f565b5b828203905092915050565b7f57524f4e475f46524f4d00000000000000000000000000000000000000000000600082015250565b6000614e89600a83613a77565b9150614e9482614e53565b602082019050919050565b60006020820190508181036000830152614eb881614e7c565b9050919050565b7f494e56414c49445f524543495049454e54000000000000000000000000000000600082015250565b6000614ef5601183613a77565b9150614f0082614ebf565b602082019050919050565b60006020820190508181036000830152614f2481614ee8565b9050919050565b50565b6000614f3b6000836140df565b9150614f4682614f2b565b600082019050919050565b6000608082019050614f666000830186613bbc565b614f736020830185613bbc565b614f806040830184613db1565b8181036060830152614f9181614f2e565b9050949350505050565b600081519050614faa816139dd565b92915050565b600060208284031215614fc657614fc56139a7565b5b6000614fd484828501614f9b565b91505092915050565b7f554e534146455f524543495049454e5400000000000000000000000000000000600082015250565b6000615013601083613a77565b915061501e82614fdd565b602082019050919050565b6000602082019050818103600083015261504281615006565b9050919050565b82818337600083830152505050565b600061506483856140df565b9350615071838584615049565b61507a83613abb565b840190509392505050565b600060808201905061509a6000830188613bbc565b6150a76020830187613bbc565b6150b46040830186613db1565b81810360608301526150c7818486615058565b90509695505050505050565b7f414c52454144595f4d494e544544000000000000000000000000000000000000600082015250565b6000615109600e83613a77565b9150615114826150d3565b602082019050919050565b60006020820190508181036000830152615138816150fc565b9050919050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b60006151756009836146bd565b91506151808261513f565b600982019050919050565b7f222c20226465736372697074696f6e223a220000000000000000000000000000600082015250565b60006151c16012836146bd565b91506151cc8261518b565b601282019050919050565b7f4f6e636861696e204d757469706c617965722041727400000000000000000000600082015250565b600061520d6016836146bd565b9150615218826151d7565b601682019050919050565b7f222c2022696d616765223a202200000000000000000000000000000000000000600082015250565b6000615259600d836146bd565b915061526482615223565b600d82019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b60006152a56002836146bd565b91506152b08261526f565b600282019050919050565b7f2261747472696275746573223a20000000000000000000000000000000000000600082015250565b60006152f1600e836146bd565b91506152fc826152bb565b600e82019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b600061533d6001836146bd565b915061534882615307565b600182019050919050565b600061535e82615168565b915061536a8286614714565b9150615375826151b4565b915061538082615200565b915061538b8261524c565b91506153978285614714565b91506153a282615298565b91506153ad826152e4565b91506153b98284614714565b91506153c482615330565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b6000615407601d836146bd565b9150615412826153d1565b601d82019050919050565b6000615428826153fa565b91506154348284614714565b915081905092915050565b7f5475726d69746520000000000000000000000000000000000000000000000000600082015250565b60006154756008836146bd565b91506154808261543f565b600882019050919050565b7f20576f726c642000000000000000000000000000000000000000000000000000600082015250565b60006154c16007836146bd565b91506154cc8261548b565b600782019050919050565b60006154e282615468565b91506154ee8285614714565b91506154f9826154b4565b91506155058284614714565b91508190509392505050565b7f5b7b2274726169745f74797065223a22576f726c64222c2276616c7565223a22600082015250565b60006155476020836146bd565b915061555282615511565b602082019050919050565b7f227d2c0000000000000000000000000000000000000000000000000000000000600082015250565b60006155936003836146bd565b915061559e8261555d565b600382019050919050565b7f7b2274726169745f74797065223a2252756c65222c0000000000000000000000600082015250565b60006155df6015836146bd565b91506155ea826155a9565b601582019050919050565b7f2276616c7565223a220000000000000000000000000000000000000000000000600082015250565b600061562b6009836146bd565b9150615636826155f5565b600982019050919050565b7f7b2274726169745f74797065223a225374617465222c00000000000000000000600082015250565b60006156776016836146bd565b915061568282615641565b601682019050919050565b7f7b2274726169745f74797065223a22504f532058222c00000000000000000000600082015250565b60006156c36016836146bd565b91506156ce8261568d565b601682019050919050565b7f7b2274726169745f74797065223a22504f532059222c00000000000000000000600082015250565b600061570f6016836146bd565b915061571a826156d9565b601682019050919050565b7f7b2274726169745f74797065223a22446972656374696f6e222c000000000000600082015250565b600061575b601a836146bd565b915061576682615725565b601a82019050919050565b7f227d2c7b2274726169745f74797065223a224e6574776f726b222c2276616c7560008201527f65223a2200000000000000000000000000000000000000000000000000000000602082015250565b60006157cd6024836146bd565b91506157d882615771565b602482019050919050565b60008190508160005260206000209050919050565b60008154615805816142f7565b61580f81866146bd565b9450600182166000811461582a576001811461583f57615872565b60ff1983168652811515820286019350615872565b615848856157e3565b60005b8381101561586a5781548189015260018201915060208101905061584b565b838801955050505b50505092915050565b7f227d5d0000000000000000000000000000000000000000000000000000000000600082015250565b60006158b16003836146bd565b91506158bc8261587b565b600382019050919050565b60006158d28261553a565b91506158de828a614714565b91506158e982615586565b91506158f4826155d2565b91506158ff8261561e565b915061590b8289614714565b915061591682615586565b91506159218261566a565b915061592c8261561e565b91506159388288614714565b915061594382615586565b915061594e826156b6565b91506159598261561e565b91506159658287614714565b915061597082615586565b915061597b82615702565b91506159868261561e565b91506159928286614714565b915061599d82615586565b91506159a88261574e565b91506159b38261561e565b91506159bf8285614714565b91506159ca826157c0565b91506159d682846157f8565b91506159e1826158a4565b915081905098975050505050505050565b60006159fd82613cea565b9150615a0883613cea565b925082615a1857615a17614d8e565b5b828204905092915050565b6000615a2e82613cea565b9150615a3983613cea565b92508260ff03821115615a4f57615a4e614b8f565b5b828201905092915050565b6000615a6582613cea565b915060ff8203615a7857615a77614b8f565b5b60018201905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f424d385500000000000036040000280000009000000090000000010008000000000002510000120b0000120b00000000000000000000000000000101010002020200030303000404040005050500060606000707070008080800090909000a0a0a000b0b0b000c0c0c000d0d0d000e0e0e000f0f0f00101010001111110012121200131313001414140015151500161616001717170018181800191919001a1a1a001b1b1b001c1c1c001d1d1d001e1e1e001f1f1f00202020002121210022222200232323002424240025252500262626002727270028282800292929002a2a2a002b2b2b002c2c2c002d2d2d002e2e2e002f2f2f00303030003131310032323200333333003434340035353500363636003737370038383800393939003a3a3a003b3b3b003c3c3c003d3d3d003e3e3e003f3f3f00404040004141410042424200434343004444440045454500464646004747470048484800494949004a4a4a004b4b4b004c4c4c004d4d4d004e4e4e004f4f4f00505050005151510052525200535353005454540055555500565656005757570058585800595959005a5a5a005b5b5b005c5c5c005d5d5d005e5e5e005f5f5f00606060006161610062626200636363006464640065656500666666006767670068686800696969006a6a6a006b6b6b006c6c6c006d6d6d006e6e6e006f6f6f00707070007171710072727200737373007474740075757500767676007777770078787800797979007a7a7a007b7b7b007c7c7c007d7d7d007e7e7e007f7f7f00808080008181810082828200838383008484840085858500868686008787870088888800898989008a8a8a008b8b8b008c8c8c008d8d8d008e8e8e008f8f8f00909090009191910092929200939393009494940095959500969696009797970098989800999999009a9a9a009b9b9b009c9c9c009d9d9d009e9e9e009f9f9f00a0a0a000a1a1a100a2a2a200a3a3a300a4a4a400a5a5a500a6a6a600a7a7a700a8a8a800a9a9a900aaaaaa00ababab00acacac00adadad00aeaeae00afafaf00b0b0b000b1b1b100b2b2b200b3b3b300b4b4b400b5b5b500b6b6b600b7b7b700b8b8b800b9b9b900bababa00bbbbbb00bcbcbc00bdbdbd00bebebe00bfbfbf00c0c0c000c1c1c100c2c2c200c3c3c300c4c4c400c5c5c500c6c6c600c7c7c700c8c8c800c9c9c900cacaca00cbcbcb00cccccc00cdcdcd00cecece00cfcfcf00d0d0d000d1d1d100d2d2d200d3d3d300d4d4d400d5d5d500d6d6d600d7d7d700d8d8d800d9d9d900dadada00dbdbdb00dcdcdc00dddddd00dedede00dfdfdf00e0e0e000e1e1e100e2e2e200e3e3e300e4e4e400e5e5e500e6e6e600e7e7e700e8e8e800e9e9e900eaeaea00ebebeb00ececec00ededed00eeeeee00efefef00f0f0f000f1f1f100f2f2f200f3f3f300f4f4f400f5f5f500f6f6f600f7f7f700f8f8f800f9f9f900fafafa00fbfbfb00fcfcfc00fdfdfd00fefefe00ffffff00a2646970667358221220792abd84e85ae7339fc7811867b48b0df27583811acd0908f337fe392af9356364736f6c634300080f0033000000000000000000000000b955c66ff031cea247ff22be1fdbeae23977d9d70000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000084f7074696d69736d000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102065760003560e01c80636352211e1161011a578063c2a8d57c116100ad578063d3158b021161007c578063d3158b021461065c578063e524b3071461067a578063e8354445146106aa578063e985e9c5146106c6578063ef7af2fc146106f657610206565b8063c2a8d57c146105c4578063c61a3c84146105e0578063c87b56dd146105fc578063c966409d1461062c57610206565b806395d89b41116100e957806395d89b411461053e578063a22cb4651461055c578063b88d4fde14610578578063be76bf8f1461059457610206565b80636352211e1461049257806369dbd7d7146104c25780636c5453a6146104f257806370a082311461050e57610206565b80632cc4837f1161019d57806340cb8af91161016c57806340cb8af9146103ca57806342842e0e146103fa5780634f6ccce714610416578063518a8802146104465780635e8c32111461046257610206565b80632cc4837f146103305780632f745c591461034e57806335faee731461037e5780633aedf55c146103ae57610206565b80631034fc0d116101d95780631034fc0d146102a557806313f36fc1146102c157806318160ddd146102f657806323b872dd1461031457610206565b806301ffc9a71461020b57806306fdde031461023b578063081812fc14610259578063095ea7b314610289575b600080fd5b61022560048036038101906102209190613a09565b610726565b6040516102329190613a51565b60405180910390f35b6102436107b8565b6040516102509190613b05565b60405180910390f35b610273600480360381019061026e9190613b5d565b610846565b6040516102809190613bcb565b60405180910390f35b6102a3600480360381019061029e9190613c12565b610879565b005b6102bf60048036038101906102ba9190613caa565b610a62565b005b6102db60048036038101906102d69190613b5d565b610baa565b6040516102ed96959493929190613d50565b60405180910390f35b6102fe610c34565b60405161030b9190613dc0565b60405180910390f35b61032e60048036038101906103299190613ddb565b610c41565b005b610338610c6e565b6040516103459190613dc0565b60405180910390f35b61036860048036038101906103639190613c12565b610c74565b6040516103759190613dc0565b60405180910390f35b61039860048036038101906103939190613e2e565b610d19565b6040516103a59190613a51565b60405180910390f35b6103c860048036038101906103c39190613ec0565b61119d565b005b6103e460048036038101906103df9190613b5d565b6113bd565b6040516103f19190613a51565b60405180910390f35b610414600480360381019061040f9190613ddb565b6113dd565b005b610430600480360381019061042b9190613b5d565b61140a565b60405161043d9190613dc0565b60405180910390f35b610460600480360381019061045b9190613f20565b61147b565b005b61047c60048036038101906104779190613fa5565b61154f565b6040516104899190613b05565b60405180910390f35b6104ac60048036038101906104a79190613b5d565b61158e565b6040516104b99190613bcb565b60405180910390f35b6104dc60048036038101906104d79190613fa5565b611639565b6040516104e99190613b05565b60405180910390f35b61050c60048036038101906105079190613ec0565b611697565b005b61052860048036038101906105239190613f20565b6118d9565b6040516105359190613dc0565b60405180910390f35b610546611990565b6040516105539190613b05565b60405180910390f35b6105766004803603810190610571919061400c565b611a1e565b005b610592600480360381019061058d919061404c565b611b1b565b005b6105ae60048036038101906105a99190613fa5565b611b4c565b6040516105bb9190614129565b60405180910390f35b6105de60048036038101906105d9919061414b565b611d49565b005b6105fa60048036038101906105f59190613b5d565b611fc9565b005b61061660048036038101906106119190613b5d565b6120ff565b6040516106239190613b05565b60405180910390f35b6106466004803603810190610641919061419e565b6121e9565b6040516106539190613b05565b60405180910390f35b610664612200565b6040516106719190613dc0565b60405180910390f35b610694600480360381019061068f91906141cb565b612206565b6040516106a1919061421e565b60405180910390f35b6106c460048036038101906106bf919061425b565b612265565b005b6106e060048036038101906106db9190614288565b612352565b6040516106ed9190613a51565b60405180910390f35b610710600480360381019061070b9190613b5d565b612381565b60405161071d9190614129565b60405180910390f35b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061078157506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107b15750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600080546107c5906142f7565b80601f01602080910402602001604051908101604052809291908181526020018280546107f1906142f7565b801561083e5780601f106108135761010080835404028352916020019161083e565b820191906000526020600020905b81548152906001019060200180831161082157829003601f168201915b505050505081565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109715750600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6109b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a790614374565b60405180910390fd5b826004600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610a6b8261158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ad8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610acf90614374565b60405180910390fd5b60011515610ae582610d19565b151514610b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1e906143e0565b60405180910390fd5b80600b600084815260200190815260200160002060000160056101000a8154816bffffffffffffffffffffffff021916908360a01c02179055508073ffffffffffffffffffffffffffffffffffffffff1916827fd1464fd210d58c95f829eeb54351bb3b0f9cf4277440f5627f822489a0548cd360405160405180910390a35050565b600b6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900460f81b908060000160059054906101000a900460a01b905086565b6000600880549050905090565b610c4a81612450565b610c5483826124ac565b610c5e8282612619565b610c69838383612698565b505050565b600f5481565b6000610c7f836118d9565b8210610cc0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb790614472565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60008060ff60f81b836000600c8110610d3557610d34614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610da35750600060f81b836000600c8110610d7b57610d7a614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8015610e32575060ff60f81b836003600c8110610dc357610dc2614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610e315750600060f81b836003600c8110610e0957610e08614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b8015610ec1575060ff60f81b836006600c8110610e5257610e51614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610ec05750600060f81b836006600c8110610e9857610e97614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b8015610f50575060ff60f81b836009600c8110610ee157610ee0614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610f4f5750600060f81b836009600c8110610f2757610f26614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b90506000600160f81b846002600c8110610f6d57610f6c614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610fdb5750600060f81b846002600c8110610fb357610fb2614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b801561106a5750600160f81b846005600c8110610ffb57610ffa614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110695750600060f81b846005600c811061104157611040614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b80156110f95750600160f81b846008600c811061108a57611089614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110f85750600060f81b846008600c81106110d0576110cf614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b80156111885750600160f81b84600b600c811061111957611118614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806111875750600060f81b84600b600c811061115f5761115e614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b5b90508080156111945750815b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361122e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112259061450d565b60405180910390fd5b60011515601b600085815260200190815260200160002060009054906101000a900460ff16151514611295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128c9061459f565b60405180910390fd5b601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131c9061460b565b60405180910390fd5b600080600061137785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612a97565b9250925092506113b58360ff168360ff1683600b60008b815260200190815260200160002060000160039054906101000a900460ff1660ff16612ab8565b505050505050565b601b6020528060005260406000206000915054906101000a900460ff1681565b6113e681612450565b6113f083826124ac565b6113fa8282612619565b611405838383612b1d565b505050565b6000611414610c34565b8210611455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144c9061469d565b60405180910390fd5b6008828154811061146957611468614492565b5b90600052602060002001549050919050565b601a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461150b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161150290614374565b60405180910390fd5b80601960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b606061156561156086868686611b4c565b612c55565b6040516020016115759190614745565b6040516020818303038152906040529050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508173ffffffffffffffffffffffffffffffffffffffff1603611634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162b906147b3565b60405180910390fd5b919050565b606061166e61164a8686868661154f565b60405160200161165a9190614a59565b604051602081830303815290604052612c55565b60405160200161167e9190614ad2565b6040516020818303038152906040529050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611728576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161171f9061450d565b60405180910390fd5b60011515601b600085815260200190815260200160002060009054906101000a900460ff1615151461178f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117869061459f565b60405180910390fd5b601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461181f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118169061460b565b60405180910390fd5b60008061186f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612a97565b509150915081600b600087815260200190815260200160002060000160006101000a81548160ff021916908360ff16021790555080600b600087815260200190815260200160002060000160016101000a81548160ff021916908360ff1602179055505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194090614b40565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6001805461199d906142f7565b80601f01602080910402602001604051908101604052809291908181526020018280546119c9906142f7565b8015611a165780601f106119eb57610100808354040283529160200191611a16565b820191906000526020600020905b8154815290600101906020018083116119f957829003601f168201915b505050505081565b80600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b0f9190613a51565b60405180910390a35050565b611b2483612450565b611b2e85846124ac565b611b388484612619565b611b458585858585612dcd565b5050505050565b606060006040518061046001604052806104368152602001615ac461043691399050600061510067ffffffffffffffff811115611b8c57611b8b614b60565b5b6040519080825280601f01601f191660200182016040528015611bbe5781602001600182028036833780820191505090505b50905060005b6090811015611cb25760005b6090811015611ca0576000816090611be89190614bbe565b83611bf39190614c18565b9050600a60008b60ff1681526020019081526020016000206000018360908110611c2057611c1f614492565b5b600502018260908110611c3657611c35614492565b5b602091828204019190069054906101000a900460f81b848281518110611c5f57611c5e614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505080611c9990614c6e565b9050611bd0565b5080611cab90614c6e565b9050611bc4565b506001151584151503611d2a5760008560ff166090611cd19190614bbe565b8760ff16611cdf9190614c18565b905060a560f81b828281518110611cf957611cf8614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350505b611d3d8183612f0b90919063ffffffff16565b92505050949350505050565b600f54600e5410611d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8690614d02565b60405180910390fd5b60011515611d9c83610d19565b151514611dde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd5906143e0565b60405180910390fd5b601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6590614d6e565b60405180910390fd5b60016004600e54611e7f9190614dbd565b611e899190614c18565b600d81905550600060106004600e54611ea29190614dee565b60048110611eb357611eb2614492565b5b01549050600060146004600e54611eca9190614dee565b60048110611edb57611eda614492565b5b01549050611eeb85600e54612619565b611ef6600e54612f95565b611f0285600e54612fde565b611f15600e5483836001600d54896131f0565b8373ffffffffffffffffffffffffffffffffffffffff1916600e547f66e34e24596794eb9fbba61ddf385dbbc89563ac1f0250e6587c2ac6c039481d600d54604051611f619190613dc0565b60405180910390a36000831115611f7f57611f7e600e5484613354565b5b6000601b6000600e54815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600e54611fbc9190614c18565b600e819055505050505050565b600073ffffffffffffffffffffffffffffffffffffffff16601960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361205a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120519061450d565b60405180910390fd5b6120638161158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c790614374565b60405180910390fd5b6001601b600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60606121e282600b600085815260200190815260200160002060000160039054906101000a900460ff16600b600086815260200190815260200160002060000160059054906101000a900460a01b600b600087815260200190815260200160002060000160049054906101000a900460f81b600b600088815260200190815260200160002060000160009054906101000a900460ff16600b600089815260200190815260200160002060000160019054906101000a900460ff16600b60008a815260200190815260200160002060000160029054906101000a900460ff1661362c565b9050919050565b60606121f9826000806000611639565b9050919050565b600d5481565b6000600a600083815260200190815260200160002060000184609081106122305761222f614492565b5b60050201836090811061224657612245614492565b5b602091828204019190069054906101000a900460f81b90509392505050565b6122868160006002811061227c5761227b614492565b5b602002013561158e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146122f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ea90614374565b60405180910390fd5b60008160016002811061230957612308614492565b5b6020020135111561234f5761234e8160006002811061232b5761232a614492565b5b60200201358260016002811061234457612343614492565b5b6020020135613354565b5b50565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6060600080600080602067ffffffffffffffff8111156123a4576123a3614b60565b5b6040519080825280601f01601f1916602001820160405280156123d65781602001600182028036833780820191505090505b5090506000600b600088815260200190815260200160002090508054945060ff8516935060ff8560081c169250600061242e8560ff168560ff16600160048c61241f9190614dbd565b6124299190614c18565b612206565b9050846020840153836021840153806022840152829650505050505050919050565b60011515601b600083815260200190815260200160002060009054906101000a900460ff161515036124a9576000601b600083815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b600060016124b9846118d9565b6124c39190614e1f565b90506000600760008481526020019081526020016000205490508181146125a8576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000612624836118d9565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273090614e9f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279f90614f0b565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806128685750600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b806128d157506004600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290790614374565b60405180910390fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600190039190505550600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008060006001840151925060028401519150602284015190509193909250565b81600a60008381526020019081526020016000206000018560908110612ae157612ae0614492565b5b600502018460908110612af757612af6614492565b5b602091828204019190066101000a81548160ff021916908360f81c021790555050505050565b612b28838383610c41565b60008273ffffffffffffffffffffffffffffffffffffffff163b1480612c11575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168273ffffffffffffffffffffffffffffffffffffffff1663150b7a023386856040518463ffffffff1660e01b8152600401612bad93929190614f51565b6020604051808303816000875af1158015612bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf09190614fb0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b612c50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c4790615029565b60405180910390fd5b505050565b60606000825103612c7757604051806020016040528060008152509050612dc8565b6000604051806060016040528060408152602001615a846040913990506000600360028551612ca69190614c18565b612cb09190614dbd565b6004612cbc9190614bbe565b90506000602082612ccd9190614c18565b67ffffffffffffffff811115612ce657612ce5614b60565b5b6040519080825280601f01601f191660200182016040528015612d185781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612d87576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612d2c565b600389510660018114612da15760028114612db157612dbc565b613d3d60f01b6002830352612dbc565b603d60f81b60018303525b50505050508093505050505b919050565b612dd8858585610c41565b60008473ffffffffffffffffffffffffffffffffffffffff163b1480612ec5575063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663150b7a0233888787876040518663ffffffff1660e01b8152600401612e61959493929190615085565b6020604051808303816000875af1158015612e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea49190614fb0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b612f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612efb90615029565b60405180910390fd5b5050505050565b6060806040519050835180825260208201818101602087015b81831015612f415780518352602083019250602081019050612f24565b50855192508351830184528091508282019050602086015b81831015612f765780518352602083019250602081019050612f59565b50601f19601f8851850115830101166040525050508091505092915050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361304d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161304490614f0b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146130ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130e69061511f565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60006040518060c001604052808760ff1681526020018660ff1681526020018560ff1681526020018460ff168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020018373ffffffffffffffffffffffffffffffffffffffff1916815250600b600089815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548160ff021916908360ff16021790555060608201518160000160036101000a81548160ff021916908360ff16021790555060808201518160000160046101000a81548160ff021916908360f81c021790555060a08201518160000160056101000a8154816bffffffffffffffffffffffff021916908360a01c021790555090505050505050505050565b600080600080600080600b600089815260200190815260200160002090508054915060005b878110156135ec5760ff8316955060ff8360081c1694508260181c935060006133ac8760ff168760ff168760ff16612206565b905070ffffffffffffffffffffffff0000000000841660ff8560101c16600080600064ff00000000891660201c1460008660f81c141615613400578360781b9b5060ff8460781c16905060ff8460701c1691505b600064ff00000000891660201c1460ff8660f81c141615613434578360901b9b5060ff8460601c16905060ff8460581c1691505b600164ff00000000891660201c1460008660f81c141615613468578360a81b9b5060ff8460481c16905060ff8460401c1691505b600164ff00000000891660201c1460ff8660f81c14161561349c578360c01b9b5060ff8460301c16905060ff8460281c1691505b600081600281146134bf57600881146134cc57600481146134ee578491506134f8565b60046001860891506134f8565b84600081146134e3576004600187030692506134e8565b600392505b506134f8565b6004600286010691505b50604051816000811461352257600281146135385760038114613569576001811461357f576135ac565b609060018f08601f8301538c601e8301536135ac565b8d600081146135555760018f03601f8401538d601e840153613563565b608f601f8401538d601e8401535b506135ac565b8d601f830153609060018e08601e8301536135ac565b8c6000811461359c578e601f84015360018e03601e8401536135aa565b8e601f840153608f601e8401535b505b5081601d8201538a601c82015383601b8201538581511799505050505050506135e08760ff168760ff168a8860ff16612ab8565b60018201915050613379565b50818155868360ff16897fbbe0aa2504840f3cabeaa7c222bc975ed888abf937945ff374653c8d57c55fbb60405160405180910390a45050505050505050565b606061367c61363b89896136a8565b6136488987876001611639565b6136568a8a8a8a8a8a6136e7565b60405160200161366893929190615353565b604051602081830303815290604052612c55565b60405160200161368c919061541d565b6040516020818303038152906040529050979650505050505050565b60606136b383613764565b6136bf8360ff16613764565b6040516020016136d09291906154d7565b604051602081830303815290604052905092915050565b60606136f58760ff16613764565b6136fe876137b4565b61370d8760f81c60ff16613764565b6137198760ff16613764565b6137258760ff16613764565b6137318760ff16613764565b600c60405160200161374997969594939291906158c7565b60405160208183030381529060405290509695505050505050565b606060a060405101806040526020810391506000825281835b60011561379f57600184039350600a81066030018453600a810490508061377d575b50828103602084039350808452505050919050565b6060600080601867ffffffffffffffff8111156137d4576137d3614b60565b5b6040519080825280601f01601f1916602001820160405280156138065781602001600182028036833780820191505090505b509050600091505b80518260ff161015613960576000600f60f81b8560028561382f91906159f2565b60ff16600c811061384357613842614492565b5b1a60f81b1660f81c9050600060048660028661385f91906159f2565b60ff16600c811061387357613872614492565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60f81c90506138a98161396a565b838560ff16815181106138bf576138be614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001846138fb9190615a23565b93506139068261396a565b838560ff168151811061391c5761391b614492565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505050818061395890615a5a565b92505061380e565b8092505050919050565b6000600a8260ff16101561398f576030826139859190615a23565b60f81b90506139a2565b60578261399c9190615a23565b60f81b90505b919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6139e6816139b1565b81146139f157600080fd5b50565b600081359050613a03816139dd565b92915050565b600060208284031215613a1f57613a1e6139a7565b5b6000613a2d848285016139f4565b91505092915050565b60008115159050919050565b613a4b81613a36565b82525050565b6000602082019050613a666000830184613a42565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613aa6578082015181840152602081019050613a8b565b83811115613ab5576000848401525b50505050565b6000601f19601f8301169050919050565b6000613ad782613a6c565b613ae18185613a77565b9350613af1818560208601613a88565b613afa81613abb565b840191505092915050565b60006020820190508181036000830152613b1f8184613acc565b905092915050565b6000819050919050565b613b3a81613b27565b8114613b4557600080fd5b50565b600081359050613b5781613b31565b92915050565b600060208284031215613b7357613b726139a7565b5b6000613b8184828501613b48565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613bb582613b8a565b9050919050565b613bc581613baa565b82525050565b6000602082019050613be06000830184613bbc565b92915050565b613bef81613baa565b8114613bfa57600080fd5b50565b600081359050613c0c81613be6565b92915050565b60008060408385031215613c2957613c286139a7565b5b6000613c3785828601613bfd565b9250506020613c4885828601613b48565b9150509250929050565b60007fffffffffffffffffffffffff000000000000000000000000000000000000000082169050919050565b613c8781613c52565b8114613c9257600080fd5b50565b600081359050613ca481613c7e565b92915050565b60008060408385031215613cc157613cc06139a7565b5b6000613ccf85828601613b48565b9250506020613ce085828601613c95565b9150509250929050565b600060ff82169050919050565b613d0081613cea565b82525050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613d3b81613d06565b82525050565b613d4a81613c52565b82525050565b600060c082019050613d656000830189613cf7565b613d726020830188613cf7565b613d7f6040830187613cf7565b613d8c6060830186613cf7565b613d996080830185613d32565b613da660a0830184613d41565b979650505050505050565b613dba81613b27565b82525050565b6000602082019050613dd56000830184613db1565b92915050565b600080600060608486031215613df457613df36139a7565b5b6000613e0286828701613bfd565b9350506020613e1386828701613bfd565b9250506040613e2486828701613b48565b9150509250925092565b600060208284031215613e4457613e436139a7565b5b6000613e5284828501613c95565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613e8057613e7f613e5b565b5b8235905067ffffffffffffffff811115613e9d57613e9c613e60565b5b602083019150836001820283011115613eb957613eb8613e65565b5b9250929050565b600080600060408486031215613ed957613ed86139a7565b5b6000613ee786828701613b48565b935050602084013567ffffffffffffffff811115613f0857613f076139ac565b5b613f1486828701613e6a565b92509250509250925092565b600060208284031215613f3657613f356139a7565b5b6000613f4484828501613bfd565b91505092915050565b613f5681613cea565b8114613f6157600080fd5b50565b600081359050613f7381613f4d565b92915050565b613f8281613a36565b8114613f8d57600080fd5b50565b600081359050613f9f81613f79565b92915050565b60008060008060808587031215613fbf57613fbe6139a7565b5b6000613fcd87828801613f64565b9450506020613fde87828801613f64565b9350506040613fef87828801613f64565b925050606061400087828801613f90565b91505092959194509250565b60008060408385031215614023576140226139a7565b5b600061403185828601613bfd565b925050602061404285828601613f90565b9150509250929050565b600080600080600060808688031215614068576140676139a7565b5b600061407688828901613bfd565b955050602061408788828901613bfd565b945050604061409888828901613b48565b935050606086013567ffffffffffffffff8111156140b9576140b86139ac565b5b6140c588828901613e6a565b92509250509295509295909350565b600081519050919050565b600082825260208201905092915050565b60006140fb826140d4565b61410581856140df565b9350614115818560208601613a88565b61411e81613abb565b840191505092915050565b6000602082019050818103600083015261414381846140f0565b905092915050565b600080600060608486031215614164576141636139a7565b5b600061417286828701613bfd565b935050602061418386828701613c95565b925050604061419486828701613b48565b9150509250925092565b6000602082840312156141b4576141b36139a7565b5b60006141c284828501613f64565b91505092915050565b6000806000606084860312156141e4576141e36139a7565b5b60006141f286828701613b48565b935050602061420386828701613b48565b925050604061421486828701613b48565b9150509250925092565b60006020820190506142336000830184613d32565b92915050565b60008190508260206002028201111561425557614254613e65565b5b92915050565b600060408284031215614271576142706139a7565b5b600061427f84828501614239565b91505092915050565b6000806040838503121561429f5761429e6139a7565b5b60006142ad85828601613bfd565b92505060206142be85828601613bfd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061430f57607f821691505b602082108103614322576143216142c8565b5b50919050565b7f4e4f545f415554484f52495a4544000000000000000000000000000000000000600082015250565b600061435e600e83613a77565b915061436982614328565b602082019050919050565b6000602082019050818103600083015261438d81614351565b9050919050565b7f494e56414c49445f52554c450000000000000000000000000000000000000000600082015250565b60006143ca600c83613a77565b91506143d582614394565b602082019050919050565b600060208201905081810360008301526143f9816143bd565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b600061445c602b83613a77565b915061446782614400565b604082019050919050565b6000602082019050818103600083015261448b8161444f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f434f4e54524143545f49535f5a45524f41444452455353000000000000000000600082015250565b60006144f7601783613a77565b9150614502826144c1565b602082019050919050565b60006020820190508181036000830152614526816144ea565b9050919050565b7f434f4e54524143545f4e4f545f494e4954414c495a45445f42595f4e46545f4f60008201527f574e455200000000000000000000000000000000000000000000000000000000602082015250565b6000614589602483613a77565b91506145948261452d565b604082019050919050565b600060208201905081810360008301526145b88161457c565b9050919050565b7f43414c4c5f4f4e4c595f46524f4d5f4841434f4e545241435400000000000000600082015250565b60006145f5601983613a77565b9150614600826145bf565b602082019050919050565b60006020820190508181036000830152614624816145e8565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614687602c83613a77565b91506146928261462b565b604082019050919050565b600060208201905081810360008301526146b68161467a565b9050919050565b600081905092915050565b7f646174613a696d6167652f626d703b6261736536342c00000000000000000000600082015250565b60006146fe6016836146bd565b9150614709826146c8565b601682019050919050565b600061471f82613a6c565b61472981856146bd565b9350614739818560208601613a88565b80840191505092915050565b6000614750826146f1565b915061475c8284614714565b915081905092915050565b7f4e4f545f4d494e54454400000000000000000000000000000000000000000000600082015250565b600061479d600a83613a77565b91506147a882614767565b602082019050919050565b600060208201905081810360008301526147cc81614790565b9050919050565b7f3c73766720636c6173733d227376674247472220786d6c6e733d22687474703a60008201527f2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d2260208201527f312e31222077696474683d2235303022206865696768743d22353030223e3c6460408201527f6566732069643d22736f6d6544656673223e3c7374796c652069643d2273747960608201527f6c6531393939223e202e737667424747207b2077696474683a2035303070783b60808201527f6865696768743a2035303070783b6261636b67726f756e642d696d6167653a2060a08201527f75726c280000000000000000000000000000000000000000000000000000000060c082015250565b60006148ed60c4836146bd565b91506148f8826147d3565b60c482019050919050565b7f293b206261636b67726f756e642d7265706561743a206e6f2d7265706561743b60008201527f206261636b67726f756e642d73697a653a20313030253b20696d6167652d726560208201527f6e646572696e673a202d7765626b69742d6f7074696d697a652d636f6e74726160408201527f73743b202d6d732d696e746572706f6c6174696f6e2d6d6f64653a206e65617260608201527f6573742d6e65696768626f723b20696d6167652d72656e646572696e673a202d60808201527f6d6f7a2d63726973702d65646765733b20696d6167652d72656e646572696e6760a08201527f3a20706978656c617465643b7d3c2f7374796c653e3c2f646566733e3c2f737660c08201527f673e00000000000000000000000000000000000000000000000000000000000060e082015250565b6000614a4360e2836146bd565b9150614a4e82614903565b60e282019050919050565b6000614a64826148e0565b9150614a708284614714565b9150614a7b82614a36565b915081905092915050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000600082015250565b6000614abc601a836146bd565b9150614ac782614a86565b601a82019050919050565b6000614add82614aaf565b9150614ae98284614714565b915081905092915050565b7f5a45524f5f414444524553530000000000000000000000000000000000000000600082015250565b6000614b2a600c83613a77565b9150614b3582614af4565b602082019050919050565b60006020820190508181036000830152614b5981614b1d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614bc982613b27565b9150614bd483613b27565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c0d57614c0c614b8f565b5b828202905092915050565b6000614c2382613b27565b9150614c2e83613b27565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614c6357614c62614b8f565b5b828201905092915050565b6000614c7982613b27565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614cab57614caa614b8f565b5b600182019050919050565b7f4d494e545f4f5645520000000000000000000000000000000000000000000000600082015250565b6000614cec600983613a77565b9150614cf782614cb6565b602082019050919050565b60006020820190508181036000830152614d1b81614cdf565b9050919050565b7f4f4e4c595f4d494e5441424c455f46524f4d5f4d494e545f434f4e5452414354600082015250565b6000614d58602083613a77565b9150614d6382614d22565b602082019050919050565b60006020820190508181036000830152614d8781614d4b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614dc882613b27565b9150614dd383613b27565b925082614de357614de2614d8e565b5b828204905092915050565b6000614df982613b27565b9150614e0483613b27565b925082614e1457614e13614d8e565b5b828206905092915050565b6000614e2a82613b27565b9150614e3583613b27565b925082821015614e4857614e47614b8f565b5b828203905092915050565b7f57524f4e475f46524f4d00000000000000000000000000000000000000000000600082015250565b6000614e89600a83613a77565b9150614e9482614e53565b602082019050919050565b60006020820190508181036000830152614eb881614e7c565b9050919050565b7f494e56414c49445f524543495049454e54000000000000000000000000000000600082015250565b6000614ef5601183613a77565b9150614f0082614ebf565b602082019050919050565b60006020820190508181036000830152614f2481614ee8565b9050919050565b50565b6000614f3b6000836140df565b9150614f4682614f2b565b600082019050919050565b6000608082019050614f666000830186613bbc565b614f736020830185613bbc565b614f806040830184613db1565b8181036060830152614f9181614f2e565b9050949350505050565b600081519050614faa816139dd565b92915050565b600060208284031215614fc657614fc56139a7565b5b6000614fd484828501614f9b565b91505092915050565b7f554e534146455f524543495049454e5400000000000000000000000000000000600082015250565b6000615013601083613a77565b915061501e82614fdd565b602082019050919050565b6000602082019050818103600083015261504281615006565b9050919050565b82818337600083830152505050565b600061506483856140df565b9350615071838584615049565b61507a83613abb565b840190509392505050565b600060808201905061509a6000830188613bbc565b6150a76020830187613bbc565b6150b46040830186613db1565b81810360608301526150c7818486615058565b90509695505050505050565b7f414c52454144595f4d494e544544000000000000000000000000000000000000600082015250565b6000615109600e83613a77565b9150615114826150d3565b602082019050919050565b60006020820190508181036000830152615138816150fc565b9050919050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b60006151756009836146bd565b91506151808261513f565b600982019050919050565b7f222c20226465736372697074696f6e223a220000000000000000000000000000600082015250565b60006151c16012836146bd565b91506151cc8261518b565b601282019050919050565b7f4f6e636861696e204d757469706c617965722041727400000000000000000000600082015250565b600061520d6016836146bd565b9150615218826151d7565b601682019050919050565b7f222c2022696d616765223a202200000000000000000000000000000000000000600082015250565b6000615259600d836146bd565b915061526482615223565b600d82019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b60006152a56002836146bd565b91506152b08261526f565b600282019050919050565b7f2261747472696275746573223a20000000000000000000000000000000000000600082015250565b60006152f1600e836146bd565b91506152fc826152bb565b600e82019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b600061533d6001836146bd565b915061534882615307565b600182019050919050565b600061535e82615168565b915061536a8286614714565b9150615375826151b4565b915061538082615200565b915061538b8261524c565b91506153978285614714565b91506153a282615298565b91506153ad826152e4565b91506153b98284614714565b91506153c482615330565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b6000615407601d836146bd565b9150615412826153d1565b601d82019050919050565b6000615428826153fa565b91506154348284614714565b915081905092915050565b7f5475726d69746520000000000000000000000000000000000000000000000000600082015250565b60006154756008836146bd565b91506154808261543f565b600882019050919050565b7f20576f726c642000000000000000000000000000000000000000000000000000600082015250565b60006154c16007836146bd565b91506154cc8261548b565b600782019050919050565b60006154e282615468565b91506154ee8285614714565b91506154f9826154b4565b91506155058284614714565b91508190509392505050565b7f5b7b2274726169745f74797065223a22576f726c64222c2276616c7565223a22600082015250565b60006155476020836146bd565b915061555282615511565b602082019050919050565b7f227d2c0000000000000000000000000000000000000000000000000000000000600082015250565b60006155936003836146bd565b915061559e8261555d565b600382019050919050565b7f7b2274726169745f74797065223a2252756c65222c0000000000000000000000600082015250565b60006155df6015836146bd565b91506155ea826155a9565b601582019050919050565b7f2276616c7565223a220000000000000000000000000000000000000000000000600082015250565b600061562b6009836146bd565b9150615636826155f5565b600982019050919050565b7f7b2274726169745f74797065223a225374617465222c00000000000000000000600082015250565b60006156776016836146bd565b915061568282615641565b601682019050919050565b7f7b2274726169745f74797065223a22504f532058222c00000000000000000000600082015250565b60006156c36016836146bd565b91506156ce8261568d565b601682019050919050565b7f7b2274726169745f74797065223a22504f532059222c00000000000000000000600082015250565b600061570f6016836146bd565b915061571a826156d9565b601682019050919050565b7f7b2274726169745f74797065223a22446972656374696f6e222c000000000000600082015250565b600061575b601a836146bd565b915061576682615725565b601a82019050919050565b7f227d2c7b2274726169745f74797065223a224e6574776f726b222c2276616c7560008201527f65223a2200000000000000000000000000000000000000000000000000000000602082015250565b60006157cd6024836146bd565b91506157d882615771565b602482019050919050565b60008190508160005260206000209050919050565b60008154615805816142f7565b61580f81866146bd565b9450600182166000811461582a576001811461583f57615872565b60ff1983168652811515820286019350615872565b615848856157e3565b60005b8381101561586a5781548189015260018201915060208101905061584b565b838801955050505b50505092915050565b7f227d5d0000000000000000000000000000000000000000000000000000000000600082015250565b60006158b16003836146bd565b91506158bc8261587b565b600382019050919050565b60006158d28261553a565b91506158de828a614714565b91506158e982615586565b91506158f4826155d2565b91506158ff8261561e565b915061590b8289614714565b915061591682615586565b91506159218261566a565b915061592c8261561e565b91506159388288614714565b915061594382615586565b915061594e826156b6565b91506159598261561e565b91506159658287614714565b915061597082615586565b915061597b82615702565b91506159868261561e565b91506159928286614714565b915061599d82615586565b91506159a88261574e565b91506159b38261561e565b91506159bf8285614714565b91506159ca826157c0565b91506159d682846157f8565b91506159e1826158a4565b915081905098975050505050505050565b60006159fd82613cea565b9150615a0883613cea565b925082615a1857615a17614d8e565b5b828204905092915050565b6000615a2e82613cea565b9150615a3983613cea565b92508260ff03821115615a4f57615a4e614b8f565b5b828201905092915050565b6000615a6582613cea565b915060ff8203615a7857615a77614b8f565b5b60018201905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f424d385500000000000036040000280000009000000090000000010008000000000002510000120b0000120b00000000000000000000000000000101010002020200030303000404040005050500060606000707070008080800090909000a0a0a000b0b0b000c0c0c000d0d0d000e0e0e000f0f0f00101010001111110012121200131313001414140015151500161616001717170018181800191919001a1a1a001b1b1b001c1c1c001d1d1d001e1e1e001f1f1f00202020002121210022222200232323002424240025252500262626002727270028282800292929002a2a2a002b2b2b002c2c2c002d2d2d002e2e2e002f2f2f00303030003131310032323200333333003434340035353500363636003737370038383800393939003a3a3a003b3b3b003c3c3c003d3d3d003e3e3e003f3f3f00404040004141410042424200434343004444440045454500464646004747470048484800494949004a4a4a004b4b4b004c4c4c004d4d4d004e4e4e004f4f4f00505050005151510052525200535353005454540055555500565656005757570058585800595959005a5a5a005b5b5b005c5c5c005d5d5d005e5e5e005f5f5f00606060006161610062626200636363006464640065656500666666006767670068686800696969006a6a6a006b6b6b006c6c6c006d6d6d006e6e6e006f6f6f00707070007171710072727200737373007474740075757500767676007777770078787800797979007a7a7a007b7b7b007c7c7c007d7d7d007e7e7e007f7f7f00808080008181810082828200838383008484840085858500868686008787870088888800898989008a8a8a008b8b8b008c8c8c008d8d8d008e8e8e008f8f8f00909090009191910092929200939393009494940095959500969696009797970098989800999999009a9a9a009b9b9b009c9c9c009d9d9d009e9e9e009f9f9f00a0a0a000a1a1a100a2a2a200a3a3a300a4a4a400a5a5a500a6a6a600a7a7a700a8a8a800a9a9a900aaaaaa00ababab00acacac00adadad00aeaeae00afafaf00b0b0b000b1b1b100b2b2b200b3b3b300b4b4b400b5b5b500b6b6b600b7b7b700b8b8b800b9b9b900bababa00bbbbbb00bcbcbc00bdbdbd00bebebe00bfbfbf00c0c0c000c1c1c100c2c2c200c3c3c300c4c4c400c5c5c500c6c6c600c7c7c700c8c8c800c9c9c900cacaca00cbcbcb00cccccc00cdcdcd00cecece00cfcfcf00d0d0d000d1d1d100d2d2d200d3d3d300d4d4d400d5d5d500d6d6d600d7d7d700d8d8d800d9d9d900dadada00dbdbdb00dcdcdc00dddddd00dedede00dfdfdf00e0e0e000e1e1e100e2e2e200e3e3e300e4e4e400e5e5e500e6e6e600e7e7e700e8e8e800e9e9e900eaeaea00ebebeb00ececec00ededed00eeeeee00efefef00f0f0f000f1f1f100f2f2f200f3f3f300f4f4f400f5f5f500f6f6f600f7f7f700f8f8f800f9f9f900fafafa00fbfbfb00fcfcfc00fdfdfd00fefefe00ffffff00a2646970667358221220792abd84e85ae7339fc7811867b48b0df27583811acd0908f337fe392af9356364736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b955c66ff031cea247ff22be1fdbeae23977d9d70000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000084f7074696d69736d000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _minterContract (address): 0xb955c66FF031cEA247ff22bE1fDBeAE23977d9d7
Arg [1] : maxAmount (uint256): 1024
Arg [2] : network (string): Optimism
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000b955c66ff031cea247ff22be1fdbeae23977d9d7
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000400
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [4] : 4f7074696d69736d000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.