Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 1,797 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint | 18703121 | 844 days ago | IN | 0 ETH | 0.007185 | ||||
| Mint | 18703038 | 844 days ago | IN | 0 ETH | 0.00700585 | ||||
| Mint | 18698231 | 845 days ago | IN | 0 ETH | 0.0059743 | ||||
| Mint | 18698163 | 845 days ago | IN | 0 ETH | 0.00599932 | ||||
| Mint | 18695668 | 845 days ago | IN | 0 ETH | 0.00633638 | ||||
| Mint | 18686432 | 846 days ago | IN | 0 ETH | 0.0125796 | ||||
| Mint | 18685848 | 846 days ago | IN | 0 ETH | 0.01175646 | ||||
| Mint | 18683984 | 847 days ago | IN | 0 ETH | 0.00514323 | ||||
| Mint | 18683980 | 847 days ago | IN | 0 ETH | 0.00536781 | ||||
| Mint | 18683942 | 847 days ago | IN | 0 ETH | 0.00638512 | ||||
| Mint | 18683824 | 847 days ago | IN | 0 ETH | 0.00521623 | ||||
| Mint | 18676357 | 848 days ago | IN | 0 ETH | 0.00601506 | ||||
| Mint | 18670092 | 849 days ago | IN | 0 ETH | 0.0055248 | ||||
| Mint | 18669980 | 849 days ago | IN | 0 ETH | 0.00572588 | ||||
| Mint | 18669976 | 849 days ago | IN | 0 ETH | 0.00576478 | ||||
| Mint | 18669973 | 849 days ago | IN | 0 ETH | 0.00523091 | ||||
| Mint | 18669968 | 849 days ago | IN | 0 ETH | 0.00586133 | ||||
| Mint | 18659734 | 850 days ago | IN | 0 ETH | 0.0050608 | ||||
| Mint | 18659367 | 850 days ago | IN | 0 ETH | 0.00622717 | ||||
| Mint | 18649493 | 851 days ago | IN | 0 ETH | 0.00474216 | ||||
| Mint | 18649490 | 851 days ago | IN | 0 ETH | 0.0052385 | ||||
| Mint | 18646896 | 852 days ago | IN | 0 ETH | 0.00360934 | ||||
| Mint | 18636642 | 853 days ago | IN | 0 ETH | 0.00530555 | ||||
| Mint | 18628146 | 854 days ago | IN | 0 ETH | 0.0106619 | ||||
| Mint Multiple | 18625573 | 855 days ago | IN | 0 ETH | 0.01095272 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CatalystMinter
Compiler Version
v0.6.5+commit.f956cc89
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "./Interfaces/AssetToken.sol";
import "./common/Interfaces/ERC20.sol";
import "./Interfaces/ERC20Extended.sol";
import "./common/BaseWithStorage/MetaTransactionReceiver.sol";
import "./common/Libraries/SafeMathWithRequire.sol";
import "./Catalyst/GemToken.sol";
import "./Catalyst/CatalystToken.sol";
import "./CatalystRegistry.sol";
import "./BaseWithStorage/ERC20Group.sol";
/// @notice Gateway to mint Asset with Catalyst, Gems and Sand
contract CatalystMinter is MetaTransactionReceiver {
/// @dev emitted when fee collector (that receive the sand fee) get changed
/// @param newCollector address of the new collector, address(0) means the fee will be burned
event FeeCollector(address newCollector);
function setFeeCollector(address newCollector) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_setFeeCollector(newCollector);
}
event GemAdditionFee(uint256 newFee);
function setGemAdditionFee(uint256 newFee) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_setGemAdditionFee(newFee);
}
/// @notice mint one Asset token.
/// @param from address creating the Asset, need to be the tx sender or meta tx signer.
/// @param packId unused packId that will let you predict the resulting tokenId.
/// @param metadataHash cidv1 ipfs hash of the folder where 0.json file contains the metadata.
/// @param catalystId address of the Catalyst ERC20 token to burn.
/// @param gemIds list of gem ids to burn in the catalyst.
/// @param quantity asset supply to mint
/// @param to destination address receiving the minted tokens.
/// @param data extra data.
function mint(
address from,
uint40 packId,
bytes32 metadataHash,
uint256 catalystId,
uint256[] calldata gemIds,
uint256 quantity,
address to,
bytes calldata data
) external returns (uint256) {
_checkAuthorization(from, to);
_burnCatalyst(from, catalystId);
uint16 maxGems = _checkQuantityAndBurnSandAndGems(from, catalystId, gemIds, quantity);
uint256 id = _asset.mint(from, packId, metadataHash, quantity, 0, to, data);
_catalystRegistry.setCatalyst(id, catalystId, maxGems, gemIds);
return id;
}
/// @notice associate a catalyst to a fungible Asset token by extracting it as ERC721 first.
/// @param from address from which the Asset token belongs to.
/// @param assetId tokenId of the Asset being extracted.
/// @param catalystId address of the catalyst token to use and burn.
/// @param gemIds list of gems to socket into the catalyst (burned).
/// @param to destination address receiving the extracted and upgraded ERC721 Asset token.
function extractAndChangeCatalyst(
address from,
uint256 assetId,
uint256 catalystId,
uint256[] calldata gemIds,
address to
) external returns (uint256 tokenId) {
_checkAuthorization(from, to);
tokenId = _asset.extractERC721From(from, assetId, from);
_changeCatalyst(from, tokenId, catalystId, gemIds, to);
}
/// @notice associate a new catalyst to a non-fungible Asset token.
/// @param from address from which the Asset token belongs to.
/// @param assetId tokenId of the Asset being updated.
/// @param catalystId address of the catalyst token to use and burn.
/// @param gemIds list of gems to socket into the catalyst (burned).
/// @param to destination address receiving the Asset token.
function changeCatalyst(
address from,
uint256 assetId,
uint256 catalystId,
uint256[] calldata gemIds,
address to
) external returns (uint256 tokenId) {
_checkAuthorization(from, to);
_changeCatalyst(from, assetId, catalystId, gemIds, to);
return assetId;
}
/// @notice add gems to a fungible Asset token by extracting it as ERC721 first.
/// @param from address from which the Asset token belongs to.
/// @param assetId tokenId of the Asset being extracted.
/// @param gemIds list of gems to socket into the existing catalyst (burned).
/// @param to destination address receiving the extracted and upgraded ERC721 Asset token.
function extractAndAddGems(
address from,
uint256 assetId,
uint256[] calldata gemIds,
address to
) external returns (uint256 tokenId) {
_checkAuthorization(from, to);
tokenId = _asset.extractERC721From(from, assetId, from);
_addGems(from, tokenId, gemIds, to);
}
/// @notice add gems to a non-fungible Asset token.
/// @param from address from which the Asset token belongs to.
/// @param assetId tokenId of the Asset to which the gems will be added to.
/// @param gemIds list of gems to socket into the existing catalyst (burned).
/// @param to destination address receiving the extracted and upgraded ERC721 Asset token.
function addGems(
address from,
uint256 assetId,
uint256[] calldata gemIds,
address to
) external {
_checkAuthorization(from, to);
_addGems(from, assetId, gemIds, to);
}
struct AssetData {
uint256[] gemIds;
uint256 quantity;
uint256 catalystId;
}
/// @notice mint multiple Asset tokens.
/// @param from address creating the Asset, need to be the tx sender or meta tx signer.
/// @param packId unused packId that will let you predict the resulting tokenId.
/// @param metadataHash cidv1 ipfs hash of the folder where 0.json file contains the metadata.
/// @param gemsQuantities quantities of gems to be used for each id in order
/// @param catalystsQuantities quantities of catalyst to be used for each id in order
/// @param assets contains the data to associate catalyst and gems to the assets.
/// @param to destination address receiving the minted tokens.
/// @param data extra data.
function mintMultiple(
address from,
uint40 packId,
bytes32 metadataHash,
uint256[] memory gemsQuantities,
uint256[] memory catalystsQuantities,
AssetData[] memory assets,
address to,
bytes memory data
) public returns (uint256[] memory ids) {
require(assets.length != 0, "INVALID_0_ASSETS");
_checkAuthorization(from, to);
return _mintMultiple(from, packId, metadataHash, gemsQuantities, catalystsQuantities, assets, to, data);
}
// //////////////////// INTERNALS ////////////////////
function _checkQuantityAndBurnSandAndGems(
address from,
uint256 catalystId,
uint256[] memory gemIds,
uint256 quantity
) internal returns (uint16) {
(uint16 maxGems, uint16 minQuantity, uint16 maxQuantity, uint256 sandMintingFee, ) = _getMintData(catalystId);
require(minQuantity <= quantity && quantity <= maxQuantity, "INVALID_QUANTITY");
require(gemIds.length <= maxGems, "INVALID_GEMS_TOO_MANY");
_burnSingleGems(from, gemIds);
_chargeSand(from, quantity.mul(sandMintingFee));
return maxGems;
}
function _mintMultiple(
address from,
uint40 packId,
bytes32 metadataHash,
uint256[] memory gemsQuantities,
uint256[] memory catalystsQuantities,
AssetData[] memory assets,
address to,
bytes memory data
) internal returns (uint256[] memory) {
(uint256 totalSandFee, uint256[] memory supplies, uint16[] memory maxGemsList) = _handleMultipleCatalysts(
from,
gemsQuantities,
catalystsQuantities,
assets
);
_chargeSand(from, totalSandFee);
return _mintAssets(from, packId, metadataHash, assets, supplies, maxGemsList, to, data);
}
function _chargeSand(address from, uint256 sandFee) internal {
address feeCollector = _feeCollector;
if (feeCollector != address(0) && sandFee != 0) {
if (feeCollector == address(BURN_ADDRESS)) {
// special address for burn
_sand.burnFor(from, sandFee);
} else {
_sand.transferFrom(from, _feeCollector, sandFee);
}
}
}
function _extractMintData(uint256 data)
internal
pure
returns (
uint16 maxGems,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
)
{
maxGems = uint16(data >> 240);
minQuantity = uint16((data >> 224) % 2**16);
maxQuantity = uint16((data >> 208) % 2**16);
sandMintingFee = uint256((data >> 120) % 2**88);
sandUpdateFee = uint256(data % 2**88);
}
function _getMintData(uint256 catalystId)
internal
view
returns (
uint16,
uint16,
uint16,
uint256,
uint256
)
{
if (catalystId == 0) {
return _extractMintData(_common_mint_data);
} else if (catalystId == 1) {
return _extractMintData(_rare_mint_data);
} else if (catalystId == 2) {
return _extractMintData(_epic_mint_data);
} else if (catalystId == 3) {
return _extractMintData(_legendary_mint_data);
}
return _catalysts.getMintData(catalystId);
}
function _handleMultipleCatalysts(
address from,
uint256[] memory gemsQuantities,
uint256[] memory catalystsQuantities,
AssetData[] memory assets
)
internal
returns (
uint256 totalSandFee,
uint256[] memory supplies,
uint16[] memory maxGemsList
)
{
_burnCatalysts(from, catalystsQuantities);
_burnGems(from, gemsQuantities);
supplies = new uint256[](assets.length);
maxGemsList = new uint16[](assets.length);
for (uint256 i = 0; i < assets.length; i++) {
require(catalystsQuantities[assets[i].catalystId] != 0, "INVALID_CATALYST_NOT_ENOUGH");
catalystsQuantities[assets[i].catalystId]--;
gemsQuantities = _checkGemsQuantities(gemsQuantities, assets[i].gemIds);
(uint16 maxGems, uint16 minQuantity, uint16 maxQuantity, uint256 sandMintingFee, ) = _getMintData(assets[i].catalystId);
require(minQuantity <= assets[i].quantity && assets[i].quantity <= maxQuantity, "INVALID_QUANTITY");
require(assets[i].gemIds.length <= maxGems, "INVALID_GEMS_TOO_MANY");
maxGemsList[i] = maxGems;
supplies[i] = assets[i].quantity;
totalSandFee = totalSandFee.add(sandMintingFee.mul(assets[i].quantity));
}
}
function _checkGemsQuantities(uint256[] memory gemsQuantities, uint256[] memory gemIds) internal pure returns (uint256[] memory) {
for (uint256 i = 0; i < gemIds.length; i++) {
require(gemsQuantities[gemIds[i]] != 0, "INVALID_GEMS_NOT_ENOUGH");
gemsQuantities[gemIds[i]]--;
}
return gemsQuantities;
}
function _burnCatalysts(address from, uint256[] memory catalystsQuantities) internal {
uint256[] memory ids = new uint256[](catalystsQuantities.length);
for (uint256 i = 0; i < ids.length; i++) {
ids[i] = i;
}
_catalysts.batchBurnFrom(from, ids, catalystsQuantities);
}
function _burnGems(address from, uint256[] memory gemsQuantities) internal {
uint256[] memory ids = new uint256[](gemsQuantities.length);
for (uint256 i = 0; i < ids.length; i++) {
ids[i] = i;
}
_gems.batchBurnFrom(from, ids, gemsQuantities);
}
function _mintAssets(
address from,
uint40 packId,
bytes32 metadataHash,
AssetData[] memory assets,
uint256[] memory supplies,
uint16[] memory maxGemsList,
address to,
bytes memory data
) internal returns (uint256[] memory tokenIds) {
tokenIds = _asset.mintMultiple(from, packId, metadataHash, supplies, "", to, data);
for (uint256 i = 0; i < tokenIds.length; i++) {
_catalystRegistry.setCatalyst(tokenIds[i], assets[i].catalystId, maxGemsList[i], assets[i].gemIds);
}
}
function _changeCatalyst(
address from,
uint256 assetId,
uint256 catalystId,
uint256[] memory gemIds,
address to
) internal {
require(assetId & IS_NFT != 0, "INVALID_NOT_NFT"); // Asset (ERC1155ERC721.sol) ensure NFT will return true here and non-NFT will return false
_burnCatalyst(from, catalystId);
(uint16 maxGems, , , , uint256 sandUpdateFee) = _getMintData(catalystId);
require(gemIds.length <= maxGems, "INVALID_GEMS_TOO_MANY");
_burnGems(from, gemIds);
_chargeSand(from, sandUpdateFee);
_catalystRegistry.setCatalyst(assetId, catalystId, maxGems, gemIds);
_transfer(from, to, assetId);
}
function _addGems(
address from,
uint256 assetId,
uint256[] memory gemIds,
address to
) internal {
require(assetId & IS_NFT != 0, "INVALID_NOT_NFT"); // Asset (ERC1155ERC721.sol) ensure NFT will return true here and non-NFT will return false
_catalystRegistry.addGems(assetId, gemIds);
_chargeSand(from, gemIds.length.mul(_gemAdditionFee));
_transfer(from, to, assetId);
}
function _transfer(
address from,
address to,
uint256 assetId
) internal {
if (from != to) {
_asset.safeTransferFrom(from, to, assetId);
}
}
function _checkAuthorization(address from, address to) internal view {
require(to != address(0), "INVALID_TO_ZERO_ADDRESS");
require(from == msg.sender || _metaTransactionContracts[msg.sender], "NOT_SENDER");
}
function _burnSingleGems(address from, uint256[] memory gemIds) internal {
uint256[] memory amounts = new uint256[](gemIds.length);
for (uint256 i = 0; i < gemIds.length; i++) {
amounts[i] = 1;
}
_gems.batchBurnFrom(from, gemIds, amounts);
}
function _burnCatalyst(address from, uint256 catalystId) internal {
_catalysts.burnFrom(from, catalystId, 1);
}
function _setFeeCollector(address newCollector) internal {
_feeCollector = newCollector;
emit FeeCollector(newCollector);
}
function _setGemAdditionFee(uint256 newFee) internal {
_gemAdditionFee = newFee;
emit GemAdditionFee(newFee);
}
// /////////////////// UTILITIES /////////////////////
using SafeMathWithRequire for uint256;
// //////////////////////// DATA /////////////////////
uint256 private constant IS_NFT = 0x0000000000000000000000000000000000000000800000000000000000000000;
address private constant BURN_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;
ERC20Extended internal immutable _sand;
AssetToken internal immutable _asset;
GemToken internal immutable _gems;
CatalystToken internal immutable _catalysts;
CatalystRegistry internal immutable _catalystRegistry;
address internal _feeCollector;
uint256 internal immutable _common_mint_data;
uint256 internal immutable _rare_mint_data;
uint256 internal immutable _epic_mint_data;
uint256 internal immutable _legendary_mint_data;
uint256 internal _gemAdditionFee;
// /////////////////// CONSTRUCTOR ////////////////////
constructor(
CatalystRegistry catalystRegistry,
ERC20Extended sand,
AssetToken asset,
GemToken gems,
address metaTx,
address admin,
address feeCollector,
uint256 gemAdditionFee,
CatalystToken catalysts,
uint256[4] memory bakedInMintdata
) public {
_catalystRegistry = catalystRegistry;
_sand = sand;
_asset = asset;
_gems = gems;
_catalysts = catalysts;
_admin = admin;
_setGemAdditionFee(gemAdditionFee);
_setFeeCollector(feeCollector);
_setMetaTransactionProcessor(metaTx, true);
_common_mint_data = bakedInMintdata[0];
_rare_mint_data = bakedInMintdata[1];
_epic_mint_data = bakedInMintdata[2];
_legendary_mint_data = bakedInMintdata[3];
}
}pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "./ERC20SubToken.sol";
import "../common/Libraries/SafeMath.sol";
import "../common/Libraries/AddressUtils.sol";
import "../common/Libraries/ObjectLib32.sol";
import "../common/Libraries/BytesUtil.sol";
import "../common/BaseWithStorage/SuperOperators.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
contract ERC20Group is SuperOperators, MetaTransactionReceiver {
uint256 internal constant MAX_UINT256 = ~uint256(0);
/// @notice emitted when a new Token is added to the group.
/// @param subToken the token added, its id will be its index in the array.
event SubToken(ERC20SubToken subToken);
/// @notice emitted when `owner` is allowing or disallowing `operator` to transfer tokens on its behalf.
/// @param owner the address approving.
/// @param operator the address being granted (or revoked) permission to transfer.
/// @param approved whether the operator is granted transfer right or not.
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event Minter(address minter, bool enabled);
/// @notice Enable or disable the ability of `minter` to mint tokens
/// @param minter address that will be given/removed minter right.
/// @param enabled set whether the minter is enabled or disabled.
function setMinter(address minter, bool enabled) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_setMinter(minter, enabled);
}
/// @notice check whether address `who` is given minter rights.
/// @param who The address to query.
/// @return whether the address has minter rights.
function isMinter(address who) public view returns (bool) {
return _minters[who];
}
/// @dev mint more tokens of a specific subToken .
/// @param to address receiving the tokens.
/// @param id subToken id (also the index at which it was added).
/// @param amount of token minted.
function mint(
address to,
uint256 id,
uint256 amount
) external {
require(_minters[msg.sender], "NOT_AUTHORIZED_MINTER");
(uint256 bin, uint256 index) = id.getTokenBinIndex();
mapping(uint256 => uint256) storage toPack = _packedTokenBalance[to];
toPack[bin] = toPack[bin].updateTokenBalance(index, amount, ObjectLib32.Operations.ADD);
_packedSupplies[bin] = _packedSupplies[bin].updateTokenBalance(index, amount, ObjectLib32.Operations.ADD);
_erc20s[id].emitTransferEvent(address(0), to, amount);
}
/// @dev mint more tokens of a several subToken .
/// @param to address receiving the tokens.
/// @param ids subToken ids (also the index at which it was added).
/// @param amounts for each token minted.
function batchMint(
address to,
uint256[] calldata ids,
uint256[] calldata amounts
) external {
require(_minters[msg.sender], "NOT_AUTHORIZED_MINTER");
require(ids.length == amounts.length, "INVALID_INCONSISTENT_LENGTH");
_batchMint(to, ids, amounts);
}
function _batchMint(
address to,
uint256[] memory ids,
uint256[] memory amounts
) internal {
uint256 lastBin = MAX_UINT256;
uint256 bal = 0;
uint256 supply = 0;
mapping(uint256 => uint256) storage toPack = _packedTokenBalance[to];
for (uint256 i = 0; i < ids.length; i++) {
if (amounts[i] != 0) {
(uint256 bin, uint256 index) = ids[i].getTokenBinIndex();
if (lastBin == MAX_UINT256) {
lastBin = bin;
bal = toPack[bin].updateTokenBalance(index, amounts[i], ObjectLib32.Operations.ADD);
supply = _packedSupplies[bin].updateTokenBalance(index, amounts[i], ObjectLib32.Operations.ADD);
} else {
if (bin != lastBin) {
toPack[lastBin] = bal;
bal = toPack[bin];
_packedSupplies[lastBin] = supply;
supply = _packedSupplies[bin];
lastBin = bin;
}
bal = bal.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.ADD);
supply = supply.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.ADD);
}
_erc20s[ids[i]].emitTransferEvent(address(0), to, amounts[i]);
}
}
if (lastBin != MAX_UINT256) {
toPack[lastBin] = bal;
_packedSupplies[lastBin] = supply;
}
}
/// @notice return the current total supply of a specific subToken.
/// @param id subToken id.
/// @return supply current total number of tokens.
function supplyOf(uint256 id) external view returns (uint256 supply) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
return _packedSupplies[bin].getValueInBin(index);
}
/// @notice return the balance of a particular owner for a particular subToken.
/// @param owner whose balance it is of.
/// @param id subToken id.
/// @return balance of the owner
function balanceOf(address owner, uint256 id) public view returns (uint256 balance) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
return _packedTokenBalance[owner][bin].getValueInBin(index);
}
/// @notice return the balances of a list of owners / subTokens.
/// @param owners list of addresses to which we want to know the balance.
/// @param ids list of subTokens's addresses.
/// @return balances list of balances for each request.
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory balances) {
require(owners.length == ids.length, "INVALID_INCONSISTENT_LENGTH");
balances = new uint256[](ids.length);
for (uint256 i = 0; i < ids.length; i++) {
balances[i] = balanceOf(owners[i], ids[i]);
}
}
/// @notice transfer a number of subToken from one address to another.
/// @param from owner to transfer from.
/// @param to destination address that will receive the tokens.
/// @param id subToken id.
/// @param value amount of tokens to transfer.
function singleTransferFrom(
address from,
address to,
uint256 id,
uint256 value
) external {
require(to != address(0), "INVALID_TO_ZERO_ADDRESS");
ERC20SubToken erc20 = _erc20s[id];
require(
from == msg.sender ||
msg.sender == address(erc20) ||
_metaTransactionContracts[msg.sender] ||
_superOperators[msg.sender] ||
_operatorsForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
(uint256 bin, uint256 index) = id.getTokenBinIndex();
mapping(uint256 => uint256) storage fromPack = _packedTokenBalance[from];
mapping(uint256 => uint256) storage toPack = _packedTokenBalance[to];
fromPack[bin] = fromPack[bin].updateTokenBalance(index, value, ObjectLib32.Operations.SUB);
toPack[bin] = toPack[bin].updateTokenBalance(index, value, ObjectLib32.Operations.ADD);
erc20.emitTransferEvent(from, to, value);
}
/// @notice transfer a number of different subTokens from one address to another.
/// @param from owner to transfer from.
/// @param to destination address that will receive the tokens.
/// @param ids list of subToken ids to transfer.
/// @param values list of amount for eacg subTokens to transfer.
function batchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values
) external {
require(ids.length == values.length, "INVALID_INCONSISTENT_LENGTH");
require(to != address(0), "INVALID_TO_ZERO_ADDRESS");
require(
from == msg.sender || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender] || _metaTransactionContracts[msg.sender],
"NOT_AUTHORIZED"
);
_batchTransferFrom(from, to, ids, values);
}
function _batchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal {
uint256 lastBin = MAX_UINT256;
uint256 balFrom;
uint256 balTo;
mapping(uint256 => uint256) storage fromPack = _packedTokenBalance[from];
mapping(uint256 => uint256) storage toPack = _packedTokenBalance[to];
for (uint256 i = 0; i < ids.length; i++) {
if (values[i] != 0) {
(uint256 bin, uint256 index) = ids[i].getTokenBinIndex();
if (lastBin == MAX_UINT256) {
lastBin = bin;
balFrom = ObjectLib32.updateTokenBalance(fromPack[bin], index, values[i], ObjectLib32.Operations.SUB);
balTo = ObjectLib32.updateTokenBalance(toPack[bin], index, values[i], ObjectLib32.Operations.ADD);
} else {
if (bin != lastBin) {
fromPack[lastBin] = balFrom;
toPack[lastBin] = balTo;
balFrom = fromPack[bin];
balTo = toPack[bin];
lastBin = bin;
}
balFrom = balFrom.updateTokenBalance(index, values[i], ObjectLib32.Operations.SUB);
balTo = balTo.updateTokenBalance(index, values[i], ObjectLib32.Operations.ADD);
}
ERC20SubToken erc20 = _erc20s[ids[i]];
erc20.emitTransferEvent(from, to, values[i]);
}
}
if (lastBin != MAX_UINT256) {
fromPack[lastBin] = balFrom;
toPack[lastBin] = balTo;
}
}
/// @notice grant or revoke the ability for an address to transfer token on behalf of another address.
/// @param sender address granting/revoking the approval.
/// @param operator address being granted/revoked ability to transfer.
/// @param approved whether the operator is revoked or approved.
function setApprovalForAllFor(
address sender,
address operator,
bool approved
) external {
require(msg.sender == sender || _metaTransactionContracts[msg.sender] || _superOperators[msg.sender], "NOT_AUTHORIZED");
_setApprovalForAll(sender, operator, approved);
}
/// @notice grant or revoke the ability for an address to transfer token on your behalf.
/// @param operator address being granted/revoked ability to transfer.
/// @param approved whether the operator is revoked or approved.
function setApprovalForAll(address operator, bool approved) external {
_setApprovalForAll(msg.sender, operator, approved);
}
/// @notice return whether an oeprator has the ability to transfer on behalf of another address.
/// @param owner address who would have granted the rights.
/// @param operator address being given the ability to transfer.
/// @return isOperator whether the operator has approval rigths or not.
function isApprovedForAll(address owner, address operator) external view returns (bool isOperator) {
return _operatorsForAll[owner][operator] || _superOperators[operator];
}
function isAuthorizedToTransfer(address owner, address sender) external view returns (bool) {
return _metaTransactionContracts[sender] || _superOperators[sender] || _operatorsForAll[owner][sender];
}
function isAuthorizedToApprove(address sender) external view returns (bool) {
return _metaTransactionContracts[sender] || _superOperators[sender];
}
function batchBurnFrom(
address from,
uint256[] calldata ids,
uint256[] calldata amounts
) external {
require(from != address(0), "INVALID_FROM_ZERO_ADDRESS");
require(
from == msg.sender || _metaTransactionContracts[msg.sender] || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
_batchBurnFrom(from, ids, amounts);
}
/// @notice burn token for a specific owner and subToken.
/// @param from fron which address the token are burned from.
/// @param id subToken id.
/// @param value amount of tokens to burn.
function burnFrom(
address from,
uint256 id,
uint256 value
) external {
require(
from == msg.sender || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender] || _metaTransactionContracts[msg.sender],
"NOT_AUTHORIZED"
);
_burn(from, id, value);
}
/// @notice burn token for a specific subToken.
/// @param id subToken id.
/// @param value amount of tokens to burn.
function burn(uint256 id, uint256 value) external {
_burn(msg.sender, id, value);
}
// ///////////////// INTERNAL //////////////////////////
function _batchBurnFrom(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal {
uint256 balFrom = 0;
uint256 supply = 0;
uint256 lastBin = MAX_UINT256;
mapping(uint256 => uint256) storage fromPack = _packedTokenBalance[from];
for (uint256 i = 0; i < ids.length; i++) {
if (amounts[i] != 0) {
(uint256 bin, uint256 index) = ids[i].getTokenBinIndex();
if (lastBin == MAX_UINT256) {
lastBin = bin;
balFrom = fromPack[bin].updateTokenBalance(index, amounts[i], ObjectLib32.Operations.SUB);
supply = _packedSupplies[bin].updateTokenBalance(index, amounts[i], ObjectLib32.Operations.SUB);
} else {
if (bin != lastBin) {
fromPack[lastBin] = balFrom;
balFrom = fromPack[bin];
_packedSupplies[lastBin] = supply;
supply = _packedSupplies[bin];
lastBin = bin;
}
balFrom = balFrom.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.SUB);
supply = supply.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.SUB);
}
_erc20s[ids[i]].emitTransferEvent(from, address(0), amounts[i]);
}
}
if (lastBin != MAX_UINT256) {
fromPack[lastBin] = balFrom;
_packedSupplies[lastBin] = supply;
}
}
function _burn(
address from,
uint256 id,
uint256 value
) internal {
ERC20SubToken erc20 = _erc20s[id];
(uint256 bin, uint256 index) = id.getTokenBinIndex();
mapping(uint256 => uint256) storage fromPack = _packedTokenBalance[from];
fromPack[bin] = ObjectLib32.updateTokenBalance(fromPack[bin], index, value, ObjectLib32.Operations.SUB);
_packedSupplies[bin] = ObjectLib32.updateTokenBalance(_packedSupplies[bin], index, value, ObjectLib32.Operations.SUB);
erc20.emitTransferEvent(from, address(0), value);
}
function _addSubToken(ERC20SubToken subToken) internal returns (uint256 id) {
id = _erc20s.length;
require(subToken.groupAddress() == address(this), "INVALID_GROUP");
require(subToken.groupTokenId() == id, "INVALID_ID");
_erc20s.push(subToken);
emit SubToken(subToken);
}
function _setApprovalForAll(
address sender,
address operator,
bool approved
) internal {
require(!_superOperators[operator], "INVALID_SUPER_OPERATOR");
_operatorsForAll[sender][operator] = approved;
emit ApprovalForAll(sender, operator, approved);
}
function _setMinter(address minter, bool enabled) internal {
_minters[minter] = enabled;
emit Minter(minter, enabled);
}
// ///////////////// UTILITIES /////////////////////////
using AddressUtils for address;
using ObjectLib32 for ObjectLib32.Operations;
using ObjectLib32 for uint256;
using SafeMath for uint256;
// ////////////////// DATA ///////////////////////////////
mapping(uint256 => uint256) internal _packedSupplies;
mapping(address => mapping(uint256 => uint256)) internal _packedTokenBalance;
mapping(address => mapping(address => bool)) internal _operatorsForAll;
ERC20SubToken[] internal _erc20s;
mapping(address => bool) internal _minters;
// ////////////// CONSTRUCTOR ////////////////////////////
struct SubTokenData {
string name;
string symbol;
}
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) internal {
_admin = admin;
_setMetaTransactionProcessor(metaTransactionContract, true);
_setMinter(initialMinter, true);
}
}pragma solidity 0.6.5;
import "../common/Libraries/SafeMathWithRequire.sol";
import "../common/BaseWithStorage/SuperOperators.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "./ERC20Group.sol";
contract ERC20SubToken {
// TODO add natspec, currently blocked by solidity compiler issue
event Transfer(address indexed from, address indexed to, uint256 value);
// TODO add natspec, currently blocked by solidity compiler issue
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @notice A descriptive name for the tokens
/// @return name of the tokens
function name() public view returns (string memory) {
return _name;
}
/// @notice An abbreviated name for the tokens
/// @return symbol of the tokens
function symbol() public view returns (string memory) {
return _symbol;
}
/// @notice the tokenId in ERC20Group
/// @return the tokenId in ERC20Group
function groupTokenId() external view returns (uint256) {
return _index;
}
/// @notice the ERC20Group address
/// @return the address of the group
function groupAddress() external view returns (address) {
return address(_group);
}
function totalSupply() external view returns (uint256) {
return _group.supplyOf(_index);
}
function balanceOf(address who) external view returns (uint256) {
return _group.balanceOf(who, _index);
}
function decimals() external pure returns (uint8) {
return uint8(0);
}
function transfer(address to, uint256 amount) external returns (bool success) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool success) {
if (msg.sender != from && !_group.isAuthorizedToTransfer(from, msg.sender)) {
uint256 allowance = _mAllowed[from][msg.sender];
if (allowance != ~uint256(0)) {
// save gas when allowance is maximal by not reducing it (see https://github.com/ethereum/EIPs/issues/717)
require(allowance >= amount, "NOT_AUTHOIZED_ALLOWANCE");
_mAllowed[from][msg.sender] = allowance - amount;
}
}
_transfer(from, to, amount);
return true;
}
function approve(address spender, uint256 amount) external returns (bool success) {
_approveFor(msg.sender, spender, amount);
return true;
}
function approveFor(
address from,
address spender,
uint256 amount
) external returns (bool success) {
require(msg.sender == from || _group.isAuthorizedToApprove(msg.sender), "NOT_AUTHORIZED");
_approveFor(from, spender, amount);
return true;
}
function emitTransferEvent(
address from,
address to,
uint256 amount
) external {
require(msg.sender == address(_group), "NOT_AUTHORIZED_GROUP_ONLY");
emit Transfer(from, to, amount);
}
// /////////////////// INTERNAL ////////////////////////
function _approveFor(
address owner,
address spender,
uint256 amount
) internal {
require(owner != address(0) && spender != address(0), "INVALID_FROM_OR_SPENDER");
_mAllowed[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function allowance(address owner, address spender) external view returns (uint256 remaining) {
return _mAllowed[owner][spender];
}
function _transfer(
address from,
address to,
uint256 amount
) internal {
_group.singleTransferFrom(from, to, _index, amount);
}
// ///////////////////// UTILITIES ///////////////////////
using SafeMathWithRequire for uint256;
// //////////////////// CONSTRUCTOR /////////////////////
constructor(
ERC20Group group,
uint256 index,
string memory tokenName,
string memory tokenSymbol
) public {
_group = group;
_index = index;
_name = tokenName;
_symbol = tokenSymbol;
}
// ////////////////////// DATA ///////////////////////////
ERC20Group internal immutable _group;
uint256 internal immutable _index;
mapping(address => mapping(address => uint256)) internal _mAllowed;
string internal _name;
string internal _symbol;
}pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
interface CatalystToken {
function getMintData(uint256 catalystId)
external
view
returns (
uint16 maxGems,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
);
function batchBurnFrom(
address from,
uint256[] calldata ids,
uint256[] calldata amounts
) external;
function burnFrom(
address from,
uint256 id,
uint256 amount
) external;
}pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
interface CatalystValue {
struct GemEvent {
uint256[] gemIds;
bytes32 blockHash;
}
function getValues(
uint256 catalystId,
uint256 seed,
GemEvent[] calldata events,
uint32 totalNumberOfGemTypes
) external view returns (uint32[] memory values);
}pragma solidity 0.6.5;
interface GemToken {
function batchBurnFrom(
address from,
uint256[] calldata ids,
uint256[] calldata amounts
) external;
}pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "./Interfaces/AssetToken.sol";
import "./common/BaseWithStorage/Admin.sol";
import "./Catalyst/CatalystValue.sol";
contract CatalystRegistry is Admin, CatalystValue {
event Minter(address indexed newMinter);
event CatalystApplied(uint256 indexed assetId, uint256 indexed catalystId, uint256 seed, uint256[] gemIds, uint64 blockNumber);
event GemsAdded(uint256 indexed assetId, uint256 seed, uint256[] gemIds, uint64 blockNumber);
function getCatalyst(uint256 assetId) external view returns (bool exists, uint256 catalystId) {
CatalystStored memory catalyst = _catalysts[assetId];
if (catalyst.set != 0) {
return (true, catalyst.catalystId);
}
if (assetId & IS_NFT != 0) {
catalyst = _catalysts[_getCollectionId(assetId)];
return (catalyst.set != 0, catalyst.catalystId);
}
return (false, 0);
}
function setCatalyst(
uint256 assetId,
uint256 catalystId,
uint256 maxGems,
uint256[] calldata gemIds
) external {
require(msg.sender == _minter, "NOT_AUTHORIZED_MINTER");
require(gemIds.length <= maxGems, "INVALID_GEMS_TOO_MANY");
uint256 emptySockets = maxGems - gemIds.length;
_catalysts[assetId] = CatalystStored(uint64(emptySockets), uint64(catalystId), 1);
uint64 blockNumber = _getBlockNumber();
emit CatalystApplied(assetId, catalystId, assetId, gemIds, blockNumber);
}
function addGems(uint256 assetId, uint256[] calldata gemIds) external {
require(msg.sender == _minter, "NOT_AUTHORIZED_MINTER");
require(assetId & IS_NFT != 0, "INVALID_NOT_NFT");
require(gemIds.length != 0, "INVALID_GEMS_0");
(uint256 emptySockets, uint256 seed) = _getSocketData(assetId);
require(emptySockets >= gemIds.length, "INVALID_GEMS_TOO_MANY");
emptySockets -= gemIds.length;
_catalysts[assetId].emptySockets = uint64(emptySockets);
uint64 blockNumber = _getBlockNumber();
emit GemsAdded(assetId, seed, gemIds, blockNumber);
}
/// @dev Set the Minter that will be the only address able to create Estate
/// @param minter address of the minter
function setMinter(address minter) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
require(minter != _minter, "INVALID_MINTER_SAME_ALREADY_SET");
_minter = minter;
emit Minter(minter);
}
/// @dev return the current minter
function getMinter() external view returns (address) {
return _minter;
}
function getValues(
uint256 catalystId,
uint256 seed,
GemEvent[] calldata events,
uint32 totalNumberOfGemTypes
) external override view returns (uint32[] memory values) {
return _catalystValue.getValues(catalystId, seed, events, totalNumberOfGemTypes);
}
// ///////// INTERNAL ////////////
uint256 private constant IS_NFT = 0x0000000000000000000000000000000000000000800000000000000000000000;
uint256 private constant NOT_IS_NFT = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFFFFFFFFF;
uint256 private constant NOT_NFT_INDEX = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000007FFFFFFFFFFFFFFF;
function _getSocketData(uint256 assetId) internal view returns (uint256 emptySockets, uint256 seed) {
seed = assetId;
CatalystStored memory catalyst = _catalysts[assetId];
if (catalyst.set != 0) {
// the gems are added to an asset who already get a specific catalyst.
// the seed is its id
return (catalyst.emptySockets, seed);
}
// else the asset is only adding gems while keeping the same seed (that of the original assetId)
seed = _getCollectionId(assetId);
catalyst = _catalysts[seed];
return (catalyst.emptySockets, seed);
}
function _getBlockNumber() internal view returns (uint64 blockNumber) {
blockNumber = uint64(block.number + 1);
}
function _getCollectionId(uint256 assetId) internal pure returns (uint256) {
return assetId & NOT_NFT_INDEX & NOT_IS_NFT; // compute the same as Asset to get collectionId
}
// CONSTRUCTOR ////
constructor(CatalystValue catalystValue, address admin) public {
_admin = admin;
_catalystValue = catalystValue;
}
/// DATA ////////
struct CatalystStored {
uint64 emptySockets;
uint64 catalystId;
uint64 set;
}
address internal _minter;
CatalystValue internal immutable _catalystValue;
mapping(uint256 => CatalystStored) internal _catalysts;
}pragma solidity 0.6.5;
interface AssetToken {
function mint(
address creator,
uint40 packId,
bytes32 hash,
uint256 supply,
uint8 rarity,
address owner,
bytes calldata data
) external returns (uint256 id);
function mintMultiple(
address creator,
uint40 packId,
bytes32 hash,
uint256[] calldata supplies,
bytes calldata rarityPack,
address owner,
bytes calldata data
) external returns (uint256[] memory ids);
// fails on non-NFT or nft who do not have collection (was a mistake)
function collectionOf(uint256 id) external view returns (uint256);
function balanceOf(address owner, uint256 id) external view returns (uint256);
// return true for Non-NFT ERC1155 tokens which exists
function isCollection(uint256 id) external view returns (bool);
function collectionIndexOf(uint256 id) external view returns (uint256);
function extractERC721From(
address sender,
uint256 id,
address to
) external returns (uint256 newId);
function transferFrom(
address from,
address to,
uint256 id
) external;
function safeTransferFrom(
address from,
address to,
uint256 id
) external;
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 value,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}pragma solidity 0.6.5;
import "../common/Interfaces/ERC20.sol";
interface ERC20Extended is ERC20 {
function burnFor(address from, uint256 amount) external;
function burn(uint256 amount) external;
function approveFor(
address owner,
address spender,
uint256 amount
) external returns (bool success);
}pragma solidity 0.6.5;
contract Admin {
address internal _admin;
/// @dev emitted when the contract administrator is changed.
/// @param oldAdmin address of the previous administrator.
/// @param newAdmin address of the new administrator.
event AdminChanged(address oldAdmin, address newAdmin);
/// @dev gives the current administrator of this contract.
/// @return the current administrator of this contract.
function getAdmin() external view returns (address) {
return _admin;
}
/// @dev change the administrator to be `newAdmin`.
/// @param newAdmin address of the new administrator.
function changeAdmin(address newAdmin) external {
require(msg.sender == _admin, "only admin can change admin");
emit AdminChanged(_admin, newAdmin);
_admin = newAdmin;
}
modifier onlyAdmin() {
require(msg.sender == _admin, "only admin allowed");
_;
}
}pragma solidity 0.6.5;
import "./Admin.sol";
contract MetaTransactionReceiver is Admin {
mapping(address => bool) internal _metaTransactionContracts;
/// @dev emiited when a meta transaction processor is enabled/disabled
/// @param metaTransactionProcessor address that will be given/removed metaTransactionProcessor rights.
/// @param enabled set whether the metaTransactionProcessor is enabled or disabled.
event MetaTransactionProcessor(address metaTransactionProcessor, bool enabled);
/// @dev Enable or disable the ability of `metaTransactionProcessor` to perform meta-tx (metaTransactionProcessor rights).
/// @param metaTransactionProcessor address that will be given/removed metaTransactionProcessor rights.
/// @param enabled set whether the metaTransactionProcessor is enabled or disabled.
function setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) public {
require(msg.sender == _admin, "only admin can setup metaTransactionProcessors");
_setMetaTransactionProcessor(metaTransactionProcessor, enabled);
}
function _setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) internal {
_metaTransactionContracts[metaTransactionProcessor] = enabled;
emit MetaTransactionProcessor(metaTransactionProcessor, enabled);
}
/// @dev check whether address `who` is given meta-transaction execution rights.
/// @param who The address to query.
/// @return whether the address has meta-transaction execution rights.
function isMetaTransactionProcessor(address who) external view returns (bool) {
return _metaTransactionContracts[who];
}
}pragma solidity 0.6.5;
import "./Admin.sol";
contract SuperOperators is Admin {
mapping(address => bool) internal _superOperators;
event SuperOperator(address superOperator, bool enabled);
/// @notice Enable or disable the ability of `superOperator` to transfer tokens of all (superOperator rights).
/// @param superOperator address that will be given/removed superOperator right.
/// @param enabled set whether the superOperator is enabled or disabled.
function setSuperOperator(address superOperator, bool enabled) external {
require(msg.sender == _admin, "only admin is allowed to add super operators");
_superOperators[superOperator] = enabled;
emit SuperOperator(superOperator, enabled);
}
/// @notice check whether address `who` is given superOperator rights.
/// @param who The address to query.
/// @return whether the address has superOperator rights.
function isSuperOperator(address who) public view returns (bool) {
return _superOperators[who];
}
}pragma solidity 0.6.5;
/// @dev see https://eips.ethereum.org/EIPS/eip-20
interface ERC20 {
/// @notice emitted when tokens are transfered from one address to another.
/// @param from address from which the token are transfered from (zero means tokens are minted).
/// @param to destination address which the token are transfered to (zero means tokens are burnt).
/// @param value amount of tokens transferred.
event Transfer(address indexed from, address indexed to, uint256 value);
/// @notice emitted when owner grant transfer rights to another address
/// @param owner address allowing its token to be transferred.
/// @param spender address allowed to spend on behalf of `owner`
/// @param value amount of tokens allowed.
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @notice return the current total amount of tokens owned by all holders.
/// @return supply total number of tokens held.
function totalSupply() external view returns (uint256 supply);
/// @notice return the number of tokens held by a particular address.
/// @param who address being queried.
/// @return balance number of token held by that address.
function balanceOf(address who) external view returns (uint256 balance);
/// @notice transfer tokens to a specific address.
/// @param to destination address receiving the tokens.
/// @param value number of tokens to transfer.
/// @return success whether the transfer succeeded.
function transfer(address to, uint256 value) external returns (bool success);
/// @notice transfer tokens from one address to another.
/// @param from address tokens will be sent from.
/// @param to destination address receiving the tokens.
/// @param value number of tokens to transfer.
/// @return success whether the transfer succeeded.
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool success);
/// @notice approve an address to spend on your behalf.
/// @param spender address entitled to transfer on your behalf.
/// @param value amount allowed to be transfered.
/// @param success whether the approval succeeded.
function approve(address spender, uint256 value) external returns (bool success);
/// @notice return the current allowance for a particular owner/spender pair.
/// @param owner address allowing spender.
/// @param spender address allowed to spend.
/// @return amount number of tokens `spender` can spend on behalf of `owner`.
function allowance(address owner, address spender) external view returns (uint256 amount);
}pragma solidity 0.6.5;
library AddressUtils {
function toPayable(address _address) internal pure returns (address payable _payable) {
return address(uint160(_address));
}
function isContract(address addr) internal view returns (bool) {
// for accounts without code, i.e. `keccak256('')`:
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
bytes32 codehash;
// solium-disable-next-line security/no-inline-assembly
assembly {
codehash := extcodehash(addr)
}
return (codehash != 0x0 && codehash != accountHash);
}
}pragma solidity 0.6.5;
library BytesUtil {
function memcpy(
uint256 dest,
uint256 src,
uint256 len
) internal pure {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint256 mask = 256**(32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
function pointerToBytes(uint256 src, uint256 len) internal pure returns (bytes memory) {
bytes memory ret = new bytes(len);
uint256 retptr;
assembly {
retptr := add(ret, 32)
}
memcpy(retptr, src, len);
return ret;
}
function addressToBytes(address a) internal pure returns (bytes memory b) {
assembly {
let m := mload(0x40)
mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, a))
mstore(0x40, add(m, 52))
b := m
}
}
function uint256ToBytes(uint256 a) internal pure returns (bytes memory b) {
assembly {
let m := mload(0x40)
mstore(add(m, 32), a)
mstore(0x40, add(m, 64))
b := m
}
}
function doFirstParamEqualsAddress(bytes memory data, address _address) internal pure returns (bool) {
if (data.length < (36 + 32)) {
return false;
}
uint256 value;
assembly {
value := mload(add(data, 36))
}
return value == uint256(_address);
}
function doParamEqualsUInt256(
bytes memory data,
uint256 i,
uint256 value
) internal pure returns (bool) {
if (data.length < (36 + (i + 1) * 32)) {
return false;
}
uint256 offset = 36 + i * 32;
uint256 valuePresent;
assembly {
valuePresent := mload(add(data, offset))
}
return valuePresent == value;
}
function overrideFirst32BytesWithAddress(bytes memory data, address _address) internal pure returns (bytes memory) {
uint256 dest;
assembly {
dest := add(data, 48)
} // 48 = 32 (offset) + 4 (func sig) + 12 (address is only 20 bytes)
bytes memory addressBytes = addressToBytes(_address);
uint256 src;
assembly {
src := add(addressBytes, 32)
}
memcpy(dest, src, 20);
return data;
}
function overrideFirstTwo32BytesWithAddressAndInt(
bytes memory data,
address _address,
uint256 _value
) internal pure returns (bytes memory) {
uint256 dest;
uint256 src;
assembly {
dest := add(data, 48)
} // 48 = 32 (offset) + 4 (func sig) + 12 (address is only 20 bytes)
bytes memory bbytes = addressToBytes(_address);
assembly {
src := add(bbytes, 32)
}
memcpy(dest, src, 20);
assembly {
dest := add(data, 68)
} // 48 = 32 (offset) + 4 (func sig) + 32 (next slot)
bbytes = uint256ToBytes(_value);
assembly {
src := add(bbytes, 32)
}
memcpy(dest, src, 32);
return data;
}
}pragma solidity 0.6.5;
import "./SafeMathWithRequire.sol";
library ObjectLib32 {
using SafeMathWithRequire for uint256;
enum Operations {ADD, SUB, REPLACE}
// Constants regarding bin or chunk sizes for balance packing
uint256 constant TYPES_BITS_SIZE = 32; // Max size of each object
uint256 constant TYPES_PER_UINT256 = 256 / TYPES_BITS_SIZE; // Number of types per uint256
//
// Objects and Tokens Functions
//
/**
* @dev Return the bin number and index within that bin where ID is
* @param tokenId Object type
* @return bin Bin number
* @return index ID's index within that bin
*/
function getTokenBinIndex(uint256 tokenId) internal pure returns (uint256 bin, uint256 index) {
bin = (tokenId * TYPES_BITS_SIZE) / 256;
index = tokenId % TYPES_PER_UINT256;
return (bin, index);
}
/**
* @dev update the balance of a type provided in binBalances
* @param binBalances Uint256 containing the balances of objects
* @param index Index of the object in the provided bin
* @param amount Value to update the type balance
* @param operation Which operation to conduct :
* Operations.REPLACE : Replace type balance with amount
* Operations.ADD : ADD amount to type balance
* Operations.SUB : Substract amount from type balance
*/
function updateTokenBalance(
uint256 binBalances,
uint256 index,
uint256 amount,
Operations operation
) internal pure returns (uint256 newBinBalance) {
uint256 objectBalance = 0;
if (operation == Operations.ADD) {
objectBalance = getValueInBin(binBalances, index);
newBinBalance = writeValueInBin(binBalances, index, objectBalance.add(amount));
} else if (operation == Operations.SUB) {
objectBalance = getValueInBin(binBalances, index);
require(objectBalance >= amount, "can't substract more than there is");
newBinBalance = writeValueInBin(binBalances, index, objectBalance.sub(amount));
} else if (operation == Operations.REPLACE) {
newBinBalance = writeValueInBin(binBalances, index, amount);
} else {
revert("Invalid operation"); // Bad operation
}
return newBinBalance;
}
/*
* @dev return value in binValue at position index
* @param binValue uint256 containing the balances of TYPES_PER_UINT256 types
* @param index index at which to retrieve value
* @return Value at given index in bin
*/
function getValueInBin(uint256 binValue, uint256 index) internal pure returns (uint256) {
// Mask to retrieve data for a given binData
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
// Shift amount
uint256 rightShift = 256 - TYPES_BITS_SIZE * (index + 1);
return (binValue >> rightShift) & mask;
}
/**
* @dev return the updated binValue after writing amount at index
* @param binValue uint256 containing the balances of TYPES_PER_UINT256 types
* @param index Index at which to retrieve value
* @param amount Value to store at index in bin
* @return Value at given index in bin
*/
function writeValueInBin(
uint256 binValue,
uint256 index,
uint256 amount
) internal pure returns (uint256) {
require(amount < 2**TYPES_BITS_SIZE, "Amount to write in bin is too large");
// Mask to retrieve data for a given binData
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
// Shift amount
uint256 leftShift = 256 - TYPES_BITS_SIZE * (index + 1);
return (binValue & ~(mask << leftShift)) | (amount << leftShift);
}
}pragma solidity 0.6.5;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}pragma solidity 0.6.5;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert
*/
library SafeMathWithRequire {
using SafeMathWithRequire for uint256;
uint256 constant DECIMALS_18 = 1000000000000000000;
uint256 constant DECIMALS_12 = 1000000000000;
uint256 constant DECIMALS_9 = 1000000000;
uint256 constant DECIMALS_6 = 1000000;
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
c = a * b;
require(c / a == b, "overflow");
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "divbyzero");
// uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "undeflow");
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a, "overflow");
return c;
}
function sqrt6(uint256 a) internal pure returns (uint256 c) {
a = a.mul(DECIMALS_12);
uint256 tmp = a.add(1) / 2;
c = a;
// tmp cannot be zero unless a = 0 which skip the loop
while (tmp < c) {
c = tmp;
tmp = ((a / tmp) + tmp) / 2;
}
}
function sqrt3(uint256 a) internal pure returns (uint256 c) {
a = a.mul(DECIMALS_6);
uint256 tmp = a.add(1) / 2;
c = a;
// tmp cannot be zero unless a = 0 which skip the loop
while (tmp < c) {
c = tmp;
tmp = ((a / tmp) + tmp) / 2;
}
}
function cbrt6(uint256 a) internal pure returns (uint256 c) {
a = a.mul(DECIMALS_18);
uint256 tmp = a.add(2) / 3;
c = a;
// tmp cannot be zero unless a = 0 which skip the loop
while (tmp < c) {
c = tmp;
uint256 tmpSquare = tmp**2;
require(tmpSquare > tmp, "overflow");
tmp = ((a / tmpSquare) + (tmp * 2)) / 3;
}
return c;
}
function cbrt3(uint256 a) internal pure returns (uint256 c) {
a = a.mul(DECIMALS_9);
uint256 tmp = a.add(2) / 3;
c = a;
// tmp cannot be zero unless a = 0 which skip the loop
while (tmp < c) {
c = tmp;
uint256 tmpSquare = tmp**2;
require(tmpSquare > tmp, "overflow");
tmp = ((a / tmpSquare) + (tmp * 2)) / 3;
}
return c;
}
// TODO test
function rt6_3(uint256 a) internal pure returns (uint256 c) {
a = a.mul(DECIMALS_18);
uint256 tmp = a.add(5) / 6;
c = a;
// tmp cannot be zero unless a = 0 which skip the loop
while (tmp < c) {
c = tmp;
uint256 tmpFive = tmp**5;
require(tmpFive > tmp, "overflow");
tmp = ((a / tmpFive) + (tmp * 5)) / 6;
}
}
}{
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 2000
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract CatalystRegistry","name":"catalystRegistry","type":"address"},{"internalType":"contract ERC20Extended","name":"sand","type":"address"},{"internalType":"contract AssetToken","name":"asset","type":"address"},{"internalType":"contract GemToken","name":"gems","type":"address"},{"internalType":"address","name":"metaTx","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"feeCollector","type":"address"},{"internalType":"uint256","name":"gemAdditionFee","type":"uint256"},{"internalType":"contract CatalystToken","name":"catalysts","type":"address"},{"internalType":"uint256[4]","name":"bakedInMintdata","type":"uint256[4]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newCollector","type":"address"}],"name":"FeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"GemAdditionFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"metaTransactionProcessor","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"MetaTransactionProcessor","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"addGems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"catalystId","type":"uint256"},{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"changeCatalyst","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"extractAndAddGems","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"catalystId","type":"uint256"},{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"extractAndChangeCatalyst","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"isMetaTransactionProcessor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint40","name":"packId","type":"uint40"},{"internalType":"bytes32","name":"metadataHash","type":"bytes32"},{"internalType":"uint256","name":"catalystId","type":"uint256"},{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint40","name":"packId","type":"uint40"},{"internalType":"bytes32","name":"metadataHash","type":"bytes32"},{"internalType":"uint256[]","name":"gemsQuantities","type":"uint256[]"},{"internalType":"uint256[]","name":"catalystsQuantities","type":"uint256[]"},{"components":[{"internalType":"uint256[]","name":"gemIds","type":"uint256[]"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"catalystId","type":"uint256"}],"internalType":"struct CatalystMinter.AssetData[]","name":"assets","type":"tuple[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintMultiple","outputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCollector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setGemAdditionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metaTransactionProcessor","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setMetaTransactionProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101a06040523480156200001257600080fd5b5060405162002a6f38038062002a6f8339810160408190526200003591620001e6565b6001600160601b031960608b811b8216610100528a811b821660805289811b821660a05288811b821660c05283901b1660e052600080546001600160a01b0387166001600160a01b031990911617905562000099836001600160e01b03620000f316565b620000ad846001600160e01b036200013516565b620000c38660016001600160e01b036200018216565b80516101205260208101516101405260408101516101605260600151610180525062000375975050505050505050565b60038190556040517fd1f666866bc45129492a51e011fa6b5a25db558c3bbdffbaf0dbbdbc57347403906200012a90839062000353565b60405180910390a150565b600280546001600160a01b0319166001600160a01b0383161790556040517ffa62ad95255db03db5eaabed7a43b93f377948b56cea8e12a747b6565582ed5e906200012a90839062000324565b6001600160a01b03821660009081526001602052604090819020805460ff1916831515179055517fb21eb88b4e33b3f1281830a7178d74d8aa73220416215726b68ae23d539515cb90620001da908490849062000338565b60405180910390a15050565b6000806000806000806000806000806101a08b8d03121562000206578586fd5b8a5162000213816200035c565b60208c0151909a5062000226816200035c565b60408c015190995062000239816200035c565b60608c01519098506200024c816200035c565b60808c01519097506200025f816200035c565b60a08c015190965062000272816200035c565b60c08c015190955062000285816200035c565b60e08c01516101008d01519195509350620002a0816200035c565b915061013f8b018c13620002b2578081fd5b604051608081016001600160401b0381118282101715620002d1578283fd5b604052806101208d016101a08e018f1015620002eb578384fd5b835b60048110156200030e578151835260209283019290910190600101620002ed565b505050809150509295989b9194979a5092959850565b6001600160a01b0391909116815260200190565b6001600160a01b039290921682521515602082015260400190565b90815260200190565b6001600160a01b03811681146200037257600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205161014051610160516101805161264c62000423600039806110b352508061108152508061104f52508061100e525080610479528061090c5280610c8252806116cc525080610a555280611107528061187852508061122c52806112f052508061039b528061056b52806106e85280610f975280611627525080610e1c5280610ebd525061264c6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063c8929ab011610081578063e8aab9571161005b578063e8aab957146101b8578063eb94619f146101cb578063f2c0d1e7146101de576100d4565b8063c8929ab014610165578063d2fcbd2e14610178578063dc5074af14610198576100d4565b80638f283970116100b25780638f2839701461011f5780638f42403a14610132578063a42dce8014610152576100d4565b80636e9960c3146100d95780637011ead3146100f75780638a04af6a1461010c575b600080fd5b6100e16101f1565b6040516100ee9190612001565b60405180910390f35b61010a610105366004611bd5565b610200565b005b61010a61011a366004611b9e565b610251565b61010a61012d366004611b7c565b610292565b610145610140366004611da2565b61033d565b6040516100ee91906124f2565b61010a610160366004611b7c565b6104f9565b610145610173366004611c44565b61052f565b61018b610186366004611cbb565b610643565b6040516100ee919061221a565b6101ab6101a6366004611b7c565b61068e565b6040516100ee919061222d565b6101456101c6366004611bd5565b6106ac565b6101456101d9366004611c44565b6107be565b61010a6101ec366004611f97565b610816565b6000546001600160a01b031690565b61020a8582610849565b61024a85858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508792506108b1915050565b5050505050565b6000546001600160a01b031633146102845760405162461bcd60e51b815260040161027b90612382565b60405180910390fd5b61028e82826109a5565b5050565b6000546001600160a01b031633146102bc5760405162461bcd60e51b815260040161027b9061244d565b6000546040517f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f916102fb916001600160a01b03909116908490612015565b60405180910390a1600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60006103498b85610849565b6103538b89610a25565b60006103958c8a8a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250610ac5915050565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c50a4eb98e8e8e8b60008c8c8c6040518963ffffffff1660e01b81526004016103f49897969594939291906121ab565b602060405180830381600087803b15801561040e57600080fd5b505af1158015610422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104469190611faf565b6040517f1b74ea650000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631b74ea65906104b69084908e9087908f908f9060040161251c565b600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50929f9e505050505050505050505050505050565b6000546001600160a01b031633146105235760405162461bcd60e51b815260040161027b90612314565b61052c81610b63565b50565b600061053b8783610849565b6040517fff23be530000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ff23be53906105a4908a908a9082906004016120bb565b602060405180830381600087803b1580156105be57600080fd5b505af11580156105d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f69190611faf565b9050610639878287878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250610bd1915050565b9695505050505050565b60608351600014156106675760405162461bcd60e51b815260040161027b90612238565b6106718984610849565b6106818989898989898989610d03565b9998505050505050505050565b6001600160a01b031660009081526001602052604090205460ff1690565b60006106b88683610849565b6040517fff23be530000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ff23be5390610721908990899082906004016120bb565b602060405180830381600087803b15801561073b57600080fd5b505af115801561074f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107739190611faf565b90506107b586828686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508892506108b1915050565b95945050505050565b60006107ca8783610849565b61080b878787878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250610bd1915050565b509395945050505050565b6000546001600160a01b031633146108405760405162461bcd60e51b815260040161027b90612314565b61052c81610d46565b6001600160a01b03811661086f5760405162461bcd60e51b815260040161027b9061226f565b6001600160a01b03821633148061089557503360009081526001602052604090205460ff165b61028e5760405162461bcd60e51b815260040161027b906123df565b6b80000000000000000000000083166108dc5760405162461bcd60e51b815260040161027b906122a6565b6040517fb07fdd1f0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b07fdd1f9061094390869086906004016124fb565b600060405180830381600087803b15801561095d57600080fd5b505af1158015610971573d6000803e3d6000fd5b505050506109948461098f6003548551610d7b90919063ffffffff16565b610dbc565b61099f848285610f4e565b50505050565b6001600160a01b0382166000908152600160205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016831515179055517fb21eb88b4e33b3f1281830a7178d74d8aa73220416215726b68ae23d539515cb90610a199084908490612087565b60405180910390a15050565b6040517f124d91e50000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063124d91e590610a8f90859085906001906004016120de565b600060405180830381600087803b158015610aa957600080fd5b505af1158015610abd573d6000803e3d6000fd5b505050505050565b6000806000806000610ad688610ffe565b509350935093509350858361ffff1611158015610af757508161ffff168611155b610b135760405162461bcd60e51b815260040161027b90612484565b8361ffff1687511115610b385760405162461bcd60e51b815260040161027b90612416565b610b4289886111a0565b610b568961098f888463ffffffff610d7b16565b5091979650505050505050565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383161790556040517ffa62ad95255db03db5eaabed7a43b93f377948b56cea8e12a747b6565582ed5e90610bc6908390612001565b60405180910390a150565b6b8000000000000000000000008416610bfc5760405162461bcd60e51b815260040161027b906122a6565b610c068584610a25565b600080610c1285610ffe565b945050505091508161ffff1684511115610c3e5760405162461bcd60e51b815260040161027b90612416565b610c488785611265565b610c528782610dbc565b6040517f1b74ea650000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631b74ea6590610cbd908990899087908a90600401612588565b600060405180830381600087803b158015610cd757600080fd5b505af1158015610ceb573d6000803e3d6000fd5b50505050610cfa878488610f4e565b50505050505050565b60606000606080610d168c8a8a8a611329565b925092509250610d268c84610dbc565b610d368c8c8c8a86868c8c6115f4565b9c9b505050505050505050505050565b60038190556040517fd1f666866bc45129492a51e011fa6b5a25db558c3bbdffbaf0dbbdbc5734740390610bc69083906124f2565b600082610d8a57506000610db6565b5081810281838281610d9857fe5b0414610db65760405162461bcd60e51b815260040161027b906124bb565b92915050565b6002546001600160a01b03168015801590610dd657508115155b15610f49576001600160a01b038181161415610e8a576040517f1dd319cb0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631dd319cb90610e5390869086906004016120a2565b600060405180830381600087803b158015610e6d57600080fd5b505af1158015610e81573d6000803e3d6000fd5b50505050610f49565b6002546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926323b872dd92610ef79288921690879060040161202f565b602060405180830381600087803b158015610f1157600080fd5b505af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f9190611f1e565b505050565b816001600160a01b0316836001600160a01b031614610f49576040517f42842e0e0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610fd09086908690869060040161202f565b600060405180830381600087803b158015610fea57600080fd5b505af1158015610cfa573d6000803e3d6000fd5b60008080808085611041576110327f00000000000000000000000000000000000000000000000000000000000000006117bb565b94509450945094509450611197565b8560011415611073576110327f00000000000000000000000000000000000000000000000000000000000000006117bb565b85600214156110a5576110327f00000000000000000000000000000000000000000000000000000000000000006117bb565b85600314156110d7576110327f00000000000000000000000000000000000000000000000000000000000000006117bb565b6040517f73f164250000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906373f164259061113c9089906004016124f2565b60a06040518083038186803b15801561115457600080fd5b505afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c9190611f3a565b945094509450945094505b91939590929450565b6060815167ffffffffffffffff811180156111ba57600080fd5b506040519080825280602002602001820160405280156111e4578160200160208202803683370190505b50905060005b825181101561121457600182828151811061120157fe5b60209081029190910101526001016111ea565b50604051632014d24d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638053493490610fd090869086908690600401612053565b6060815167ffffffffffffffff8111801561127f57600080fd5b506040519080825280602002602001820160405280156112a9578160200160208202803683370190505b50905060005b81518110156112d857808282815181106112c557fe5b60209081029190910101526001016112af565b50604051632014d24d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638053493490610fd090869085908790600401612053565b600060608061133887866117ed565b6113428787611265565b835167ffffffffffffffff8111801561135a57600080fd5b50604051908082528060200260200182016040528015611384578160200160208202803683370190505b509150835167ffffffffffffffff8111801561139f57600080fd5b506040519080825280602002602001820160405280156113c9578160200160208202803683370190505b50905060005b84518110156115e957858582815181106113e557fe5b602002602001015160400151815181106113fb57fe5b6020026020010151600014156114235760405162461bcd60e51b815260040161027b906122dd565b8585828151811061143057fe5b6020026020010151604001518151811061144657fe5b602002602001018051809190600190038152505061147b8786838151811061146a57fe5b6020026020010151600001516118b1565b96506000806000806114a389868151811061149257fe5b602002602001015160400151610ffe565b5093509350935093508885815181106114b857fe5b6020026020010151602001518361ffff16111580156114f257508161ffff168986815181106114e357fe5b60200260200101516020015111155b61150e5760405162461bcd60e51b815260040161027b90612484565b8361ffff1689868151811061151f57fe5b60200260200101516000015151111561154a5760405162461bcd60e51b815260040161027b90612416565b8386868151811061155757fe5b602002602001019061ffff16908161ffff168152505088858151811061157957fe5b60200260200101516020015187868151811061159157fe5b6020026020010181815250506115d76115ca8a87815181106115af57fe5b60200260200101516020015183610d7b90919063ffffffff16565b899063ffffffff61196516565b975050600190930192506113cf915050565b509450945094915050565b6040517ff0bc00d80000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f0bc00d890611666908c908c908c908b908a908a906004016120ff565b600060405180830381600087803b15801561168057600080fd5b505af1158015611694573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116bc9190810190611e8b565b905060005b81518110156117ae577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631b74ea6583838151811061170557fe5b602002602001015189848151811061171957fe5b60200260200101516040015188858151811061173157fe5b60200260200101518b868151811061174557fe5b6020026020010151600001516040518563ffffffff1660e01b81526004016117709493929190612588565b600060405180830381600087803b15801561178a57600080fd5b505af115801561179e573d6000803e3d6000fd5b5050600190920191506116c19050565b5098975050505050505050565b60f081901c9161ffff60e083901c81169260d081901c909116916affffffffffffffffffffff607883901c8116921690565b6060815167ffffffffffffffff8111801561180757600080fd5b50604051908082528060200260200182016040528015611831578160200160208202803683370190505b50905060005b8151811015611860578082828151811061184d57fe5b6020908102919091010152600101611837565b50604051632014d24d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638053493490610fd090869085908790600401612053565b606060005b825181101561195d57838382815181106118cc57fe5b6020026020010151815181106118de57fe5b6020026020010151600014156119065760405162461bcd60e51b815260040161027b9061234b565b8383828151811061191357fe5b60200260200101518151811061192557fe5b6020908102919091010180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190526001016118b6565b509192915050565b81810182811015610db65760405162461bcd60e51b815260040161027b906124bb565b80356001600160a01b0381168114610db657600080fd5b600082601f8301126119af578081fd5b81356119c26119bd826125d8565b6125b1565b818152915060208083019084810160005b84811015611a4c5781358701606080601f19838c030112156119f457600080fd5b6119fd816125b1565b8583013567ffffffffffffffff811115611a1657600080fd5b611a248c8883870101611aa0565b82525060408381013587830152919092013590820152845292820192908201906001016119d3565b505050505092915050565b60008083601f840112611a68578081fd5b50813567ffffffffffffffff811115611a7f578182fd5b6020830191508360208083028501011115611a9957600080fd5b9250929050565b600082601f830112611ab0578081fd5b8135611abe6119bd826125d8565b818152915060208083019084810181840286018201871015611adf57600080fd5b60005b84811015611a4c57813584529282019290820190600101611ae2565b600082601f830112611b0e578081fd5b813567ffffffffffffffff811115611b24578182fd5b611b376020601f19601f840116016125b1565b9150808252836020828501011115611b4e57600080fd5b8060208401602084013760009082016020015292915050565b803564ffffffffff81168114610db657600080fd5b600060208284031215611b8d578081fd5b611b978383611988565b9392505050565b60008060408385031215611bb0578081fd5b611bba8484611988565b91506020830135611bca816125f8565b809150509250929050565b600080600080600060808688031215611bec578081fd5b611bf68787611988565b945060208601359350604086013567ffffffffffffffff811115611c18578182fd5b611c2488828901611a57565b9094509250611c3890508760608801611988565b90509295509295909350565b60008060008060008060a08789031215611c5c578081fd5b611c668888611988565b95506020870135945060408701359350606087013567ffffffffffffffff811115611c8f578182fd5b611c9b89828a01611a57565b9094509250611caf90508860808901611988565b90509295509295509295565b600080600080600080600080610100898b031215611cd7578182fd5b611ce18a8a611988565b9750611cf08a60208b01611b67565b965060408901359550606089013567ffffffffffffffff80821115611d13578384fd5b611d1f8c838d01611aa0565b965060808b0135915080821115611d34578384fd5b611d408c838d01611aa0565b955060a08b0135915080821115611d55578384fd5b611d618c838d0161199f565b9450611d708c60c08d01611988565b935060e08b0135915080821115611d85578283fd5b50611d928b828c01611afe565b9150509295985092959890939650565b6000806000806000806000806000806101008b8d031215611dc1578384fd5b611dcb8c8c611988565b9950611dda8c60208d01611b67565b985060408b0135975060608b0135965060808b013567ffffffffffffffff80821115611e04578586fd5b611e108e838f01611a57565b909850965060a08d01359550611e298e60c08f01611988565b945060e08d0135915080821115611e3e578384fd5b818d018e601f820112611e4f578485fd5b8035925081831115611e5f578485fd5b8e6020848301011115611e70578485fd5b6020810194505050809150509295989b9194979a5092959850565b60006020808385031215611e9d578182fd5b825167ffffffffffffffff811115611eb3578283fd5b80840185601f820112611ec4578384fd5b80519150611ed46119bd836125d8565b8281528381019082850185850284018601891015611ef0578687fd5b8693505b84841015611f12578051835260019390930192918501918501611ef4565b50979650505050505050565b600060208284031215611f2f578081fd5b8151611b97816125f8565b600080600080600060a08688031215611f51578283fd5b8551611f5c81612606565b6020870151909550611f6d81612606565b6040870151909450611f7e81612606565b6060870151608090970151959894975095949392505050565b600060208284031215611fa8578081fd5b5035919050565b600060208284031215611fc0578081fd5b5051919050565b6000815180845260208085019450808401835b83811015611ff657815187529582019590820190600101611fda565b509495945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0385168252606060208301526120756060830185611fc7565b82810360408401526106398185611fc7565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b60006001600160a01b038089168352602064ffffffffff89168185015287604085015260e0606085015261213660e0850188611fc7565b848103608086015261214884826124f2565b92871660a08601525083820360c085015284518083529183905b8382101561217f5786820183015181830184015290820190612162565b8382111561218f57848385830101525b601f93909301601f191692909201019998505050505050505050565b60006001600160a01b03808b16835264ffffffffff8a16602084015288604084015287606084015260ff8716608084015280861660a08401525060e060c08301528260e0830152610100838582850137828401810191909152601f909201601f19160101979650505050505050565b600060208252611b976020830184611fc7565b901515815260200190565b60208082526010908201527f494e56414c49445f305f41535345545300000000000000000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f544f5f5a45524f5f41444452455353000000000000000000604082015260600190565b6020808252600f908201527f494e56414c49445f4e4f545f4e46540000000000000000000000000000000000604082015260600190565b6020808252601b908201527f494e56414c49445f434154414c5953545f4e4f545f454e4f5547480000000000604082015260600190565b60208082526014908201527f4e4f545f415554484f52495a45445f41444d494e000000000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f47454d535f4e4f545f454e4f554748000000000000000000604082015260600190565b6020808252602e908201527f6f6e6c792061646d696e2063616e207365747570206d6574615472616e73616360408201527f74696f6e50726f636573736f7273000000000000000000000000000000000000606082015260800190565b6020808252600a908201527f4e4f545f53454e44455200000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f494e56414c49445f47454d535f544f4f5f4d414e590000000000000000000000604082015260600190565b6020808252601b908201527f6f6e6c792061646d696e2063616e206368616e67652061646d696e0000000000604082015260600190565b60208082526010908201527f494e56414c49445f5155414e5449545900000000000000000000000000000000604082015260600190565b60208082526008908201527f6f766572666c6f77000000000000000000000000000000000000000000000000604082015260600190565b90815260200190565b6000838252604060208301526125146040830184611fc7565b949350505050565b600086825285602083015261ffff85166040830152608060608301528260808301527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561256a578081fd5b60208302808560a08501379190910160a00190815295945050505050565b600085825284602083015261ffff84166040830152608060608301526106396080830184611fc7565b60405181810167ffffffffffffffff811182821017156125d057600080fd5b604052919050565b600067ffffffffffffffff8211156125ee578081fd5b5060209081020190565b801515811461052c57600080fd5b61ffff8116811461052c57600080fdfea2646970667358221220347d6f2f0399a2fe8cefd458e36464b0015333fbfa3536eded7dc33372af409764736f6c63430006050033000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa70000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db50000000000000000000000008ff2611da386de427fc96a8073963619c5851ba50000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0000000000000000000000000eaa0993e1d21c2103e4f172a20d29371fbaf6d06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f100010001ffff000000000000000000000000000000000000000000000000000000020001ffff000000000000000000000000000000000000000000000000000000030001ffff000000000000000000000000000000000000000000000000000000040001ffff0000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100d45760003560e01c8063c8929ab011610081578063e8aab9571161005b578063e8aab957146101b8578063eb94619f146101cb578063f2c0d1e7146101de576100d4565b8063c8929ab014610165578063d2fcbd2e14610178578063dc5074af14610198576100d4565b80638f283970116100b25780638f2839701461011f5780638f42403a14610132578063a42dce8014610152576100d4565b80636e9960c3146100d95780637011ead3146100f75780638a04af6a1461010c575b600080fd5b6100e16101f1565b6040516100ee9190612001565b60405180910390f35b61010a610105366004611bd5565b610200565b005b61010a61011a366004611b9e565b610251565b61010a61012d366004611b7c565b610292565b610145610140366004611da2565b61033d565b6040516100ee91906124f2565b61010a610160366004611b7c565b6104f9565b610145610173366004611c44565b61052f565b61018b610186366004611cbb565b610643565b6040516100ee919061221a565b6101ab6101a6366004611b7c565b61068e565b6040516100ee919061222d565b6101456101c6366004611bd5565b6106ac565b6101456101d9366004611c44565b6107be565b61010a6101ec366004611f97565b610816565b6000546001600160a01b031690565b61020a8582610849565b61024a85858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508792506108b1915050565b5050505050565b6000546001600160a01b031633146102845760405162461bcd60e51b815260040161027b90612382565b60405180910390fd5b61028e82826109a5565b5050565b6000546001600160a01b031633146102bc5760405162461bcd60e51b815260040161027b9061244d565b6000546040517f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f916102fb916001600160a01b03909116908490612015565b60405180910390a1600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60006103498b85610849565b6103538b89610a25565b60006103958c8a8a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250610ac5915050565b905060007f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db56001600160a01b031663c50a4eb98e8e8e8b60008c8c8c6040518963ffffffff1660e01b81526004016103f49897969594939291906121ab565b602060405180830381600087803b15801561040e57600080fd5b505af1158015610422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104469190611faf565b6040517f1b74ea650000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa71690631b74ea65906104b69084908e9087908f908f9060040161251c565b600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50929f9e505050505050505050505050505050565b6000546001600160a01b031633146105235760405162461bcd60e51b815260040161027b90612314565b61052c81610b63565b50565b600061053b8783610849565b6040517fff23be530000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db5169063ff23be53906105a4908a908a9082906004016120bb565b602060405180830381600087803b1580156105be57600080fd5b505af11580156105d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f69190611faf565b9050610639878287878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250610bd1915050565b9695505050505050565b60608351600014156106675760405162461bcd60e51b815260040161027b90612238565b6106718984610849565b6106818989898989898989610d03565b9998505050505050505050565b6001600160a01b031660009081526001602052604090205460ff1690565b60006106b88683610849565b6040517fff23be530000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db5169063ff23be5390610721908990899082906004016120bb565b602060405180830381600087803b15801561073b57600080fd5b505af115801561074f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107739190611faf565b90506107b586828686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508892506108b1915050565b95945050505050565b60006107ca8783610849565b61080b878787878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250610bd1915050565b509395945050505050565b6000546001600160a01b031633146108405760405162461bcd60e51b815260040161027b90612314565b61052c81610d46565b6001600160a01b03811661086f5760405162461bcd60e51b815260040161027b9061226f565b6001600160a01b03821633148061089557503360009081526001602052604090205460ff165b61028e5760405162461bcd60e51b815260040161027b906123df565b6b80000000000000000000000083166108dc5760405162461bcd60e51b815260040161027b906122a6565b6040517fb07fdd1f0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa7169063b07fdd1f9061094390869086906004016124fb565b600060405180830381600087803b15801561095d57600080fd5b505af1158015610971573d6000803e3d6000fd5b505050506109948461098f6003548551610d7b90919063ffffffff16565b610dbc565b61099f848285610f4e565b50505050565b6001600160a01b0382166000908152600160205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016831515179055517fb21eb88b4e33b3f1281830a7178d74d8aa73220416215726b68ae23d539515cb90610a199084908490612087565b60405180910390a15050565b6040517f124d91e50000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f1169063124d91e590610a8f90859085906001906004016120de565b600060405180830381600087803b158015610aa957600080fd5b505af1158015610abd573d6000803e3d6000fd5b505050505050565b6000806000806000610ad688610ffe565b509350935093509350858361ffff1611158015610af757508161ffff168611155b610b135760405162461bcd60e51b815260040161027b90612484565b8361ffff1687511115610b385760405162461bcd60e51b815260040161027b90612416565b610b4289886111a0565b610b568961098f888463ffffffff610d7b16565b5091979650505050505050565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383161790556040517ffa62ad95255db03db5eaabed7a43b93f377948b56cea8e12a747b6565582ed5e90610bc6908390612001565b60405180910390a150565b6b8000000000000000000000008416610bfc5760405162461bcd60e51b815260040161027b906122a6565b610c068584610a25565b600080610c1285610ffe565b945050505091508161ffff1684511115610c3e5760405162461bcd60e51b815260040161027b90612416565b610c488785611265565b610c528782610dbc565b6040517f1b74ea650000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa71690631b74ea6590610cbd908990899087908a90600401612588565b600060405180830381600087803b158015610cd757600080fd5b505af1158015610ceb573d6000803e3d6000fd5b50505050610cfa878488610f4e565b50505050505050565b60606000606080610d168c8a8a8a611329565b925092509250610d268c84610dbc565b610d368c8c8c8a86868c8c6115f4565b9c9b505050505050505050505050565b60038190556040517fd1f666866bc45129492a51e011fa6b5a25db558c3bbdffbaf0dbbdbc5734740390610bc69083906124f2565b600082610d8a57506000610db6565b5081810281838281610d9857fe5b0414610db65760405162461bcd60e51b815260040161027b906124bb565b92915050565b6002546001600160a01b03168015801590610dd657508115155b15610f49576001600160a01b038181161415610e8a576040517f1dd319cb0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d01690631dd319cb90610e5390869086906004016120a2565b600060405180830381600087803b158015610e6d57600080fd5b505af1158015610e81573d6000803e3d6000fd5b50505050610f49565b6002546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d08116926323b872dd92610ef79288921690879060040161202f565b602060405180830381600087803b158015610f1157600080fd5b505af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f9190611f1e565b505050565b816001600160a01b0316836001600160a01b031614610f49576040517f42842e0e0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db516906342842e0e90610fd09086908690869060040161202f565b600060405180830381600087803b158015610fea57600080fd5b505af1158015610cfa573d6000803e3d6000fd5b60008080808085611041576110327f00010001ffff00000000000000000000000000000000000000000000000000006117bb565b94509450945094509450611197565b8560011415611073576110327f00020001ffff00000000000000000000000000000000000000000000000000006117bb565b85600214156110a5576110327f00030001ffff00000000000000000000000000000000000000000000000000006117bb565b85600314156110d7576110327f00040001ffff00000000000000000000000000000000000000000000000000006117bb565b6040517f73f164250000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f116906373f164259061113c9089906004016124f2565b60a06040518083038186803b15801561115457600080fd5b505afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c9190611f3a565b945094509450945094505b91939590929450565b6060815167ffffffffffffffff811180156111ba57600080fd5b506040519080825280602002602001820160405280156111e4578160200160208202803683370190505b50905060005b825181101561121457600182828151811061120157fe5b60209081029190910101526001016111ea565b50604051632014d24d60e21b81526001600160a01b037f0000000000000000000000008ff2611da386de427fc96a8073963619c5851ba51690638053493490610fd090869086908690600401612053565b6060815167ffffffffffffffff8111801561127f57600080fd5b506040519080825280602002602001820160405280156112a9578160200160208202803683370190505b50905060005b81518110156112d857808282815181106112c557fe5b60209081029190910101526001016112af565b50604051632014d24d60e21b81526001600160a01b037f0000000000000000000000008ff2611da386de427fc96a8073963619c5851ba51690638053493490610fd090869085908790600401612053565b600060608061133887866117ed565b6113428787611265565b835167ffffffffffffffff8111801561135a57600080fd5b50604051908082528060200260200182016040528015611384578160200160208202803683370190505b509150835167ffffffffffffffff8111801561139f57600080fd5b506040519080825280602002602001820160405280156113c9578160200160208202803683370190505b50905060005b84518110156115e957858582815181106113e557fe5b602002602001015160400151815181106113fb57fe5b6020026020010151600014156114235760405162461bcd60e51b815260040161027b906122dd565b8585828151811061143057fe5b6020026020010151604001518151811061144657fe5b602002602001018051809190600190038152505061147b8786838151811061146a57fe5b6020026020010151600001516118b1565b96506000806000806114a389868151811061149257fe5b602002602001015160400151610ffe565b5093509350935093508885815181106114b857fe5b6020026020010151602001518361ffff16111580156114f257508161ffff168986815181106114e357fe5b60200260200101516020015111155b61150e5760405162461bcd60e51b815260040161027b90612484565b8361ffff1689868151811061151f57fe5b60200260200101516000015151111561154a5760405162461bcd60e51b815260040161027b90612416565b8386868151811061155757fe5b602002602001019061ffff16908161ffff168152505088858151811061157957fe5b60200260200101516020015187868151811061159157fe5b6020026020010181815250506115d76115ca8a87815181106115af57fe5b60200260200101516020015183610d7b90919063ffffffff16565b899063ffffffff61196516565b975050600190930192506113cf915050565b509450945094915050565b6040517ff0bc00d80000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db5169063f0bc00d890611666908c908c908c908b908a908a906004016120ff565b600060405180830381600087803b15801561168057600080fd5b505af1158015611694573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116bc9190810190611e8b565b905060005b81518110156117ae577f000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa76001600160a01b0316631b74ea6583838151811061170557fe5b602002602001015189848151811061171957fe5b60200260200101516040015188858151811061173157fe5b60200260200101518b868151811061174557fe5b6020026020010151600001516040518563ffffffff1660e01b81526004016117709493929190612588565b600060405180830381600087803b15801561178a57600080fd5b505af115801561179e573d6000803e3d6000fd5b5050600190920191506116c19050565b5098975050505050505050565b60f081901c9161ffff60e083901c81169260d081901c909116916affffffffffffffffffffff607883901c8116921690565b6060815167ffffffffffffffff8111801561180757600080fd5b50604051908082528060200260200182016040528015611831578160200160208202803683370190505b50905060005b8151811015611860578082828151811061184d57fe5b6020908102919091010152600101611837565b50604051632014d24d60e21b81526001600160a01b037f0000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f11690638053493490610fd090869085908790600401612053565b606060005b825181101561195d57838382815181106118cc57fe5b6020026020010151815181106118de57fe5b6020026020010151600014156119065760405162461bcd60e51b815260040161027b9061234b565b8383828151811061191357fe5b60200260200101518151811061192557fe5b6020908102919091010180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190526001016118b6565b509192915050565b81810182811015610db65760405162461bcd60e51b815260040161027b906124bb565b80356001600160a01b0381168114610db657600080fd5b600082601f8301126119af578081fd5b81356119c26119bd826125d8565b6125b1565b818152915060208083019084810160005b84811015611a4c5781358701606080601f19838c030112156119f457600080fd5b6119fd816125b1565b8583013567ffffffffffffffff811115611a1657600080fd5b611a248c8883870101611aa0565b82525060408381013587830152919092013590820152845292820192908201906001016119d3565b505050505092915050565b60008083601f840112611a68578081fd5b50813567ffffffffffffffff811115611a7f578182fd5b6020830191508360208083028501011115611a9957600080fd5b9250929050565b600082601f830112611ab0578081fd5b8135611abe6119bd826125d8565b818152915060208083019084810181840286018201871015611adf57600080fd5b60005b84811015611a4c57813584529282019290820190600101611ae2565b600082601f830112611b0e578081fd5b813567ffffffffffffffff811115611b24578182fd5b611b376020601f19601f840116016125b1565b9150808252836020828501011115611b4e57600080fd5b8060208401602084013760009082016020015292915050565b803564ffffffffff81168114610db657600080fd5b600060208284031215611b8d578081fd5b611b978383611988565b9392505050565b60008060408385031215611bb0578081fd5b611bba8484611988565b91506020830135611bca816125f8565b809150509250929050565b600080600080600060808688031215611bec578081fd5b611bf68787611988565b945060208601359350604086013567ffffffffffffffff811115611c18578182fd5b611c2488828901611a57565b9094509250611c3890508760608801611988565b90509295509295909350565b60008060008060008060a08789031215611c5c578081fd5b611c668888611988565b95506020870135945060408701359350606087013567ffffffffffffffff811115611c8f578182fd5b611c9b89828a01611a57565b9094509250611caf90508860808901611988565b90509295509295509295565b600080600080600080600080610100898b031215611cd7578182fd5b611ce18a8a611988565b9750611cf08a60208b01611b67565b965060408901359550606089013567ffffffffffffffff80821115611d13578384fd5b611d1f8c838d01611aa0565b965060808b0135915080821115611d34578384fd5b611d408c838d01611aa0565b955060a08b0135915080821115611d55578384fd5b611d618c838d0161199f565b9450611d708c60c08d01611988565b935060e08b0135915080821115611d85578283fd5b50611d928b828c01611afe565b9150509295985092959890939650565b6000806000806000806000806000806101008b8d031215611dc1578384fd5b611dcb8c8c611988565b9950611dda8c60208d01611b67565b985060408b0135975060608b0135965060808b013567ffffffffffffffff80821115611e04578586fd5b611e108e838f01611a57565b909850965060a08d01359550611e298e60c08f01611988565b945060e08d0135915080821115611e3e578384fd5b818d018e601f820112611e4f578485fd5b8035925081831115611e5f578485fd5b8e6020848301011115611e70578485fd5b6020810194505050809150509295989b9194979a5092959850565b60006020808385031215611e9d578182fd5b825167ffffffffffffffff811115611eb3578283fd5b80840185601f820112611ec4578384fd5b80519150611ed46119bd836125d8565b8281528381019082850185850284018601891015611ef0578687fd5b8693505b84841015611f12578051835260019390930192918501918501611ef4565b50979650505050505050565b600060208284031215611f2f578081fd5b8151611b97816125f8565b600080600080600060a08688031215611f51578283fd5b8551611f5c81612606565b6020870151909550611f6d81612606565b6040870151909450611f7e81612606565b6060870151608090970151959894975095949392505050565b600060208284031215611fa8578081fd5b5035919050565b600060208284031215611fc0578081fd5b5051919050565b6000815180845260208085019450808401835b83811015611ff657815187529582019590820190600101611fda565b509495945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0385168252606060208301526120756060830185611fc7565b82810360408401526106398185611fc7565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b60006001600160a01b038089168352602064ffffffffff89168185015287604085015260e0606085015261213660e0850188611fc7565b848103608086015261214884826124f2565b92871660a08601525083820360c085015284518083529183905b8382101561217f5786820183015181830184015290820190612162565b8382111561218f57848385830101525b601f93909301601f191692909201019998505050505050505050565b60006001600160a01b03808b16835264ffffffffff8a16602084015288604084015287606084015260ff8716608084015280861660a08401525060e060c08301528260e0830152610100838582850137828401810191909152601f909201601f19160101979650505050505050565b600060208252611b976020830184611fc7565b901515815260200190565b60208082526010908201527f494e56414c49445f305f41535345545300000000000000000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f544f5f5a45524f5f41444452455353000000000000000000604082015260600190565b6020808252600f908201527f494e56414c49445f4e4f545f4e46540000000000000000000000000000000000604082015260600190565b6020808252601b908201527f494e56414c49445f434154414c5953545f4e4f545f454e4f5547480000000000604082015260600190565b60208082526014908201527f4e4f545f415554484f52495a45445f41444d494e000000000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f47454d535f4e4f545f454e4f554748000000000000000000604082015260600190565b6020808252602e908201527f6f6e6c792061646d696e2063616e207365747570206d6574615472616e73616360408201527f74696f6e50726f636573736f7273000000000000000000000000000000000000606082015260800190565b6020808252600a908201527f4e4f545f53454e44455200000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f494e56414c49445f47454d535f544f4f5f4d414e590000000000000000000000604082015260600190565b6020808252601b908201527f6f6e6c792061646d696e2063616e206368616e67652061646d696e0000000000604082015260600190565b60208082526010908201527f494e56414c49445f5155414e5449545900000000000000000000000000000000604082015260600190565b60208082526008908201527f6f766572666c6f77000000000000000000000000000000000000000000000000604082015260600190565b90815260200190565b6000838252604060208301526125146040830184611fc7565b949350505050565b600086825285602083015261ffff85166040830152608060608301528260808301527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561256a578081fd5b60208302808560a08501379190910160a00190815295945050505050565b600085825284602083015261ffff84166040830152608060608301526106396080830184611fc7565b60405181810167ffffffffffffffff811182821017156125d057600080fd5b604052919050565b600067ffffffffffffffff8211156125ee578081fd5b5060209081020190565b801515811461052c57600080fd5b61ffff8116811461052c57600080fdfea2646970667358221220347d6f2f0399a2fe8cefd458e36464b0015333fbfa3536eded7dc33372af409764736f6c63430006050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa70000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db50000000000000000000000008ff2611da386de427fc96a8073963619c5851ba50000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0000000000000000000000000eaa0993e1d21c2103e4f172a20d29371fbaf6d06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f100010001ffff000000000000000000000000000000000000000000000000000000020001ffff000000000000000000000000000000000000000000000000000000030001ffff000000000000000000000000000000000000000000000000000000040001ffff0000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : catalystRegistry (address): 0xeFa52F2F24A82fA27FAAe3c1eC3cCa52806d1aa7
Arg [1] : sand (address): 0x3845badAde8e6dFF049820680d1F14bD3903a5d0
Arg [2] : asset (address): 0xa342f5D851E866E18ff98F351f2c6637f4478dB5
Arg [3] : gems (address): 0x8Ff2611dA386de427fC96A8073963619c5851Ba5
Arg [4] : metaTx (address): 0x3845badAde8e6dFF049820680d1F14bD3903a5d0
Arg [5] : admin (address): 0xEAA0993E1d21c2103e4f172a20D29371FbAF6D06
Arg [6] : feeCollector (address): 0x0000000000000000000000000000000000000000
Arg [7] : gemAdditionFee (uint256): 0
Arg [8] : catalysts (address): 0x2fC246149B4B8d7bcEF6188A10AF1791380227f1
Arg [9] : bakedInMintdata (uint256[4]): 1766900984260342491532585324234350259449493544918780072858173442675965952,3533748049038726821115882824977268775276977441794399030979779643968585728,5300595113817111150699180325720187291104461338670017989101385845261205504,7067442178595495480282477826463105806931945235545636947222992046553825280
-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 000000000000000000000000efa52f2f24a82fa27faae3c1ec3cca52806d1aa7
Arg [1] : 0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0
Arg [2] : 000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db5
Arg [3] : 0000000000000000000000008ff2611da386de427fc96a8073963619c5851ba5
Arg [4] : 0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0
Arg [5] : 000000000000000000000000eaa0993e1d21c2103e4f172a20d29371fbaf6d06
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000002fc246149b4b8d7bcef6188a10af1791380227f1
Arg [9] : 00010001ffff0000000000000000000000000000000000000000000000000000
Arg [10] : 00020001ffff0000000000000000000000000000000000000000000000000000
Arg [11] : 00030001ffff0000000000000000000000000000000000000000000000000000
Arg [12] : 00040001ffff0000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 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.