Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,797 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Mint | 18703121 | 356 days ago | IN | 0 ETH | 0.007185 | ||||
Mint | 18703038 | 356 days ago | IN | 0 ETH | 0.00700585 | ||||
Mint | 18698231 | 356 days ago | IN | 0 ETH | 0.0059743 | ||||
Mint | 18698163 | 356 days ago | IN | 0 ETH | 0.00599932 | ||||
Mint | 18695668 | 357 days ago | IN | 0 ETH | 0.00633638 | ||||
Mint | 18686432 | 358 days ago | IN | 0 ETH | 0.0125796 | ||||
Mint | 18685848 | 358 days ago | IN | 0 ETH | 0.01175646 | ||||
Mint | 18683984 | 358 days ago | IN | 0 ETH | 0.00514323 | ||||
Mint | 18683980 | 358 days ago | IN | 0 ETH | 0.00536781 | ||||
Mint | 18683942 | 358 days ago | IN | 0 ETH | 0.00638512 | ||||
Mint | 18683824 | 358 days ago | IN | 0 ETH | 0.00521623 | ||||
Mint | 18676357 | 359 days ago | IN | 0 ETH | 0.00601506 | ||||
Mint | 18670092 | 360 days ago | IN | 0 ETH | 0.0055248 | ||||
Mint | 18669980 | 360 days ago | IN | 0 ETH | 0.00572588 | ||||
Mint | 18669976 | 360 days ago | IN | 0 ETH | 0.00576478 | ||||
Mint | 18669973 | 360 days ago | IN | 0 ETH | 0.00523091 | ||||
Mint | 18669968 | 360 days ago | IN | 0 ETH | 0.00586133 | ||||
Mint | 18659734 | 362 days ago | IN | 0 ETH | 0.0050608 | ||||
Mint | 18659367 | 362 days ago | IN | 0 ETH | 0.00622717 | ||||
Mint | 18649493 | 363 days ago | IN | 0 ETH | 0.00474216 | ||||
Mint | 18649490 | 363 days ago | IN | 0 ETH | 0.0052385 | ||||
Mint | 18646896 | 364 days ago | IN | 0 ETH | 0.00360934 | ||||
Mint | 18636642 | 365 days ago | IN | 0 ETH | 0.00530555 | ||||
Mint | 18628146 | 366 days ago | IN | 0 ETH | 0.0106619 | ||||
Mint Multiple | 18625573 | 367 days ago | IN | 0 ETH | 0.01095272 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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
[{"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
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.