文件 1 的 76:AddressUtils.sol
pragma solidity ^0.6.0;
library AddressUtils {
function toPayable(address _address) internal pure returns (address payable _payable) {
return address(uint160(_address));
}
function isContract(address addr) internal view returns (bool) {
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
bytes32 codehash;
assembly {
codehash := extcodehash(addr)
}
return (codehash != 0x0 && codehash != accountHash);
}
}
文件 2 的 76:Admin.sol
pragma solidity ^0.6.0;
contract Admin {
address internal _admin;
event AdminChanged(address oldAdmin, address newAdmin);
function getAdmin() external view returns (address) {
return _admin;
}
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");
_;
}
}
文件 3 的 76:AdminUpgradeabilityProxy.sol
pragma solidity ^0.6.0;
import "./UpgradeabilityProxy.sol";
import "./ProxyAdmin.sol";
contract AdminUpgradeabilityProxy is UpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
constructor(
address payable _owner,
address _implementation,
bytes memory _data
) public payable UpgradeabilityProxy(_implementation, _data) {
assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
ProxyAdmin proxyAdmin = new ProxyAdmin(this, _owner);
emit AdminChanged(address(0), address(proxyAdmin));
_setAdmin(address(proxyAdmin));
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
_upgradeTo(newImplementation);
(bool success, ) = newImplementation.delegatecall(data);
require(success, "failed to call newImplementation");
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() override internal {
require(
msg.sender != _admin(),
"Cannot call fallback function from the proxy admin"
);
super._willFallback();
}
}
文件 4 的 76:AssetToken.sol
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);
function collectionOf(uint256 id) external view returns (uint256);
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 safeTransferFrom(
address from,
address to,
uint256 id
) external;
}
文件 5 的 76:BytesUtil.sol
pragma solidity ^0.6.0;
library BytesUtil {
function memcpy(
uint256 dest,
uint256 src,
uint256 len
) internal pure {
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
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)
}
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)
}
bytes memory bbytes = addressToBytes(_address);
assembly {
src := add(bbytes, 32)
}
memcpy(dest, src, 20);
assembly {
dest := add(data, 68)
}
bbytes = uint256ToBytes(_value);
assembly {
src := add(bbytes, 32)
}
memcpy(dest, src, 32);
return data;
}
}
文件 6 的 76:CatalystDataBase.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "./CatalystValue.sol";
contract CatalystDataBase is CatalystValue {
event CatalystConfiguration(uint256 indexed id, uint16 minQuantity, uint16 maxQuantity, uint256 sandMintingFee, uint256 sandUpdateFee);
function _setMintData(uint256 id, MintData memory data) internal {
_data[id] = data;
_emitConfiguration(id, data.minQuantity, data.maxQuantity, data.sandMintingFee, data.sandUpdateFee);
}
function _setValueOverride(uint256 id, CatalystValue valueOverride) internal {
_valueOverrides[id] = valueOverride;
}
function _setConfiguration(
uint256 id,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
) internal {
_data[id].minQuantity = minQuantity;
_data[id].maxQuantity = maxQuantity;
_data[id].sandMintingFee = uint88(sandMintingFee);
_data[id].sandUpdateFee = uint88(sandUpdateFee);
_emitConfiguration(id, minQuantity, maxQuantity, sandMintingFee, sandUpdateFee);
}
function _emitConfiguration(
uint256 id,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
) internal {
emit CatalystConfiguration(id, minQuantity, maxQuantity, sandMintingFee, sandUpdateFee);
}
function _computeValue(
uint256 seed,
uint256 gemId,
bytes32 blockHash,
uint256 slotIndex,
uint32 min
) internal pure returns (uint32) {
return min + uint16(uint256(keccak256(abi.encodePacked(gemId, seed, blockHash, slotIndex))) % (26 - min));
}
function getValues(
uint256 catalystId,
uint256 seed,
GemEvent[] calldata events,
uint32 totalNumberOfGemTypes
) external override view returns (uint32[] memory values) {
CatalystValue valueOverride = _valueOverrides[catalystId];
if (address(valueOverride) != address(0)) {
return valueOverride.getValues(catalystId, seed, events, totalNumberOfGemTypes);
}
values = new uint32[](totalNumberOfGemTypes);
uint32 numGems;
for (uint256 i = 0; i < events.length; i++) {
numGems += uint32(events[i].gemIds.length);
}
require(numGems <= MAX_UINT32, "TOO_MANY_GEMS");
uint32 minValue = (numGems - 1) * 5 + 1;
uint256 numGemsSoFar = 0;
for (uint256 i = 0; i < events.length; i++) {
numGemsSoFar += events[i].gemIds.length;
for (uint256 j = 0; j < events[i].gemIds.length; j++) {
uint256 gemId = events[i].gemIds[j];
uint256 slotIndex = numGemsSoFar - events[i].gemIds.length + j;
if (values[gemId] == 0) {
values[gemId] = _computeValue(seed, gemId, events[i].blockHash, slotIndex, (uint32(numGemsSoFar) - 1) * 5 + 1);
if (values[gemId] < minValue) {
values[gemId] = minValue;
}
} else {
uint32 newRoll = _computeValue(seed, gemId, events[i].blockHash, slotIndex, 1);
values[gemId] = (((values[gemId] - 1) / 25) + 1) * 25 + newRoll;
}
}
}
}
function getMintData(uint256 catalystId)
external
view
returns (
uint16 maxGems,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
)
{
maxGems = _data[catalystId].maxGems;
minQuantity = _data[catalystId].minQuantity;
maxQuantity = _data[catalystId].maxQuantity;
sandMintingFee = _data[catalystId].sandMintingFee;
sandUpdateFee = _data[catalystId].sandUpdateFee;
}
struct MintData {
uint88 sandMintingFee;
uint88 sandUpdateFee;
uint16 minQuantity;
uint16 maxQuantity;
uint16 maxGems;
}
uint32 internal constant MAX_UINT32 = 2**32 - 1;
mapping(uint256 => MintData) internal _data;
mapping(uint256 => CatalystValue) internal _valueOverrides;
}
文件 7 的 76:CatalystMinter.sol
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";
contract CatalystMinter is MetaTransactionReceiver {
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);
}
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;
}
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);
}
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;
}
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);
}
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;
}
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);
}
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)) {
_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");
_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");
_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);
}
using SafeMathWithRequire for uint256;
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(
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];
}
}
文件 8 的 76:CatalystRegistry.sol
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);
}
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);
}
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);
}
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) {
return (catalyst.emptySockets, seed);
}
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;
}
constructor(CatalystValue catalystValue, address admin) public {
_admin = admin;
_catalystValue = catalystValue;
}
struct CatalystStored {
uint64 emptySockets;
uint64 catalystId;
uint64 set;
}
address internal _minter;
CatalystValue internal immutable _catalystValue;
mapping(uint256 => CatalystStored) internal _catalysts;
}
文件 9 的 76:CatalystToken.sol
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;
}
文件 10 的 76:CatalystValue.sol
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);
}
文件 11 的 76:ERC1155.sol
pragma solidity ^0.6.0;
interface ERC1155 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 value,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
function balanceOf(address owner, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 12 的 76:ERC1155BaseToken.sol
pragma solidity 0.6.5;
import "../../common/Interfaces/ERC1155.sol";
import "../../common/Interfaces/ERC1155TokenReceiver.sol";
import "../../common/Libraries/AddressUtils.sol";
import "../../common/Libraries/ObjectLib32.sol";
import "../../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../../common/BaseWithStorage/SuperOperators.sol";
contract ERC1155BaseToken is MetaTransactionReceiver, SuperOperators, ERC1155 {
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 value,
bytes calldata data
) external override {
bool metaTx = _transferFrom(from, to, id, value);
require(_checkERC1155AndCallSafeTransfer(metaTx ? from : msg.sender, from, to, id, value, data), "erc1155 transfer rejected");
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external override {
require(ids.length == values.length, "Inconsistent array length between args");
require(to != address(0), "destination is zero address");
require(from != address(0), "from is zero address");
bool metaTx = _metaTransactionContracts[msg.sender];
require(from == msg.sender || metaTx || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender], "not authorized");
_batchTransferFrom(from, to, ids, values);
emit TransferBatch(metaTx ? from : msg.sender, from, to, ids, values);
require(_checkERC1155AndCallSafeBatchTransfer(metaTx ? from : msg.sender, from, to, ids, values, data), "erc1155 transfer rejected");
}
function balanceOf(address owner, uint256 id) public override view returns (uint256) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
return _packedTokenBalance[owner][bin].getValueInBin(index);
}
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external override view returns (uint256[] memory) {
require(owners.length == ids.length, "Inconsistent array length between args");
uint256[] memory balances = new uint256[](ids.length);
for (uint256 i = 0; i < ids.length; i++) {
balances[i] = balanceOf(owners[i], ids[i]);
}
return balances;
}
function setApprovalForAllFor(
address sender,
address operator,
bool approved
) external {
require(msg.sender == sender || _metaTransactionContracts[msg.sender] || _superOperators[msg.sender], "require meta approval");
_setApprovalForAll(sender, operator, approved);
}
function setApprovalForAll(address operator, bool approved) external override {
_setApprovalForAll(msg.sender, operator, approved);
}
function isApprovedForAll(address owner, address operator) external override view returns (bool isOperator) {
require(owner != address(0), "owner is zero address");
require(operator != address(0), "operator is zero address");
return _operatorsForAll[owner][operator] || _superOperators[operator];
}
function supportsInterface(bytes4 id) external pure returns (bool) {
return
id == ERC165ID ||
id == 0xd9b67a26;
}
function batchBurnFrom(
address from,
uint256[] calldata ids,
uint256[] calldata amounts
) external {
require(from != address(0), "from is zero address");
bool metaTx = _metaTransactionContracts[msg.sender];
require(from == msg.sender || metaTx || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender], "not authorized");
uint256 balFrom;
uint256 lastBin = ~uint256(0);
for (uint256 i = 0; i < ids.length; i++) {
if (amounts[i] > 0) {
(uint256 bin, uint256 index) = ids[i].getTokenBinIndex();
if (lastBin == ~uint256(0)) {
lastBin = bin;
balFrom = ObjectLib32.updateTokenBalance(_packedTokenBalance[from][bin], index, amounts[i], ObjectLib32.Operations.SUB);
} else {
if (bin != lastBin) {
_packedTokenBalance[from][lastBin] = balFrom;
balFrom = _packedTokenBalance[from][bin];
lastBin = bin;
}
balFrom = balFrom.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.SUB);
}
}
}
if (lastBin != ~uint256(0)) {
_packedTokenBalance[from][lastBin] = balFrom;
}
emit TransferBatch(metaTx ? from : msg.sender, from, address(0), ids, amounts);
}
function burn(uint256 id, uint256 amount) external {
_burn(msg.sender, msg.sender, id, amount);
}
function burnFrom(
address from,
uint256 id,
uint256 amount
) external {
require(from != address(0), "from is zero address");
bool metaTx = _metaTransactionContracts[msg.sender];
require(from == msg.sender || metaTx || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender], "not authorized");
_burn(metaTx ? from : msg.sender, from, id, amount);
}
function _transferFrom(
address from,
address to,
uint256 id,
uint256 value
) internal returns (bool metaTx) {
require(to != address(0), "destination is zero address");
require(from != address(0), "from is zero address");
metaTx = _metaTransactionContracts[msg.sender];
require(from == msg.sender || metaTx || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender], "Operator not approved");
if (value > 0) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
_packedTokenBalance[from][bin] = _packedTokenBalance[from][bin].updateTokenBalance(index, value, ObjectLib32.Operations.SUB);
_packedTokenBalance[to][bin] = _packedTokenBalance[to][bin].updateTokenBalance(index, value, ObjectLib32.Operations.ADD);
}
emit TransferSingle(metaTx ? from : msg.sender, from, to, id, value);
}
function _batchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal {
uint256 numItems = ids.length;
uint256 bin;
uint256 index;
uint256 balFrom;
uint256 balTo;
uint256 lastBin = ~uint256(0);
for (uint256 i = 0; i < numItems; i++) {
if (values[i] > 0) {
(bin, index) = ids[i].getTokenBinIndex();
if (lastBin == ~uint256(0)) {
lastBin = bin;
balFrom = ObjectLib32.updateTokenBalance(_packedTokenBalance[from][bin], index, values[i], ObjectLib32.Operations.SUB);
balTo = ObjectLib32.updateTokenBalance(_packedTokenBalance[to][bin], index, values[i], ObjectLib32.Operations.ADD);
} else {
if (bin != lastBin) {
_packedTokenBalance[from][lastBin] = balFrom;
_packedTokenBalance[to][lastBin] = balTo;
balFrom = _packedTokenBalance[from][bin];
balTo = _packedTokenBalance[to][bin];
lastBin = bin;
}
balFrom = balFrom.updateTokenBalance(index, values[i], ObjectLib32.Operations.SUB);
balTo = balTo.updateTokenBalance(index, values[i], ObjectLib32.Operations.ADD);
}
}
}
if (lastBin != ~uint256(0)) {
_packedTokenBalance[from][lastBin] = balFrom;
_packedTokenBalance[to][lastBin] = balTo;
}
}
function _setApprovalForAll(
address sender,
address operator,
bool approved
) internal {
require(sender != address(0), "sender is zero address");
require(sender != operator, "sender = operator");
require(operator != address(0), "operator is zero address");
require(!_superOperators[operator], "super operator can't have their approvalForAll changed");
_operatorsForAll[sender][operator] = approved;
emit ApprovalForAll(sender, operator, approved);
}
function _burn(
address operator,
address from,
uint256 id,
uint256 amount
) internal {
require(amount > 0 && amount <= MAX_SUPPLY, "invalid amount");
(uint256 bin, uint256 index) = (id).getTokenBinIndex();
_packedTokenBalance[from][bin] = _packedTokenBalance[from][bin].updateTokenBalance(index, amount, ObjectLib32.Operations.SUB);
emit TransferSingle(operator, from, address(0), id, amount);
}
function checkIsERC1155Receiver(address _contract) internal view returns (bool) {
bool success;
bool result;
bytes memory call_data = abi.encodeWithSelector(ERC165ID, ERC1155_IS_RECEIVER);
assembly {
let call_ptr := add(0x20, call_data)
let call_size := mload(call_data)
let output := mload(0x40)
mstore(output, 0x0)
success := staticcall(10000, _contract, call_ptr, call_size, output, 0x20)
result := mload(output)
}
assert(gasleft() > 158);
return success && result;
}
function _checkERC1155AndCallSafeTransfer(
address operator,
address from,
address to,
uint256 id,
uint256 value,
bytes memory data
) internal returns (bool) {
if (!to.isContract()) {
return true;
}
return ERC1155TokenReceiver(to).onERC1155Received(operator, from, id, value, data) == ERC1155_RECEIVED;
}
function _checkERC1155AndCallSafeBatchTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal returns (bool) {
if (!to.isContract()) {
return true;
}
bytes4 retval = ERC1155TokenReceiver(to).onERC1155BatchReceived(operator, from, ids, values, data);
return (retval == ERC1155_BATCH_RECEIVED);
}
using AddressUtils for address;
using ObjectLib32 for ObjectLib32.Operations;
using ObjectLib32 for uint256;
bytes4 internal constant ERC165ID = 0x01ffc9a7;
bytes4 internal constant ERC1155_IS_RECEIVER = 0x4e2312e0;
bytes4 internal constant ERC1155_RECEIVED = 0xf23a6e61;
bytes4 internal constant ERC1155_BATCH_RECEIVED = 0xbc197c81;
uint256 internal constant MAX_SUPPLY = uint256(2)**32 - 1;
mapping(address => mapping(uint256 => uint256)) internal _packedTokenBalance;
mapping(address => mapping(address => bool)) internal _operatorsForAll;
constructor(address metaTransactionContract, address admin) internal {
_setMetaTransactionProcessor(metaTransactionContract, true);
_admin = admin;
}
}
文件 13 的 76:ERC1155Catalyst.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../../BaseWithStorage/wip/MintableERC1155Token.sol";
import "../CatalystDataBase.sol";
contract ERC1155Catalyst is CatalystDataBase, MintableERC1155Token {
function addCatalysts(string[] memory names, MintData[] memory data) public {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
require(names.length == data.length, "INVALID_INCONSISTENT_LENGTH");
uint256 count = _count;
for (uint256 i = 0; i < data.length; i++) {
_names[count + i] = names[i];
_data[count + i] = data[i];
}
_count = count + data.length;
}
function addCatalyst(string memory name, MintData memory data) public {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
uint256 count = _count;
_names[count] = name;
_data[count] = data;
_count++;
}
uint256 _count;
mapping(uint256 => string) _names;
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) public MintableERC1155Token(metaTransactionContract, admin, initialMinter) {}
}
文件 14 的 76:ERC1155Gem.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../../BaseWithStorage/wip/MintableERC1155Token.sol";
contract ERC1155Gem is MintableERC1155Token {
function addGems(string[] memory names) public {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_addGems(names);
}
function _addGems(string[] memory names) internal {
uint256 count = _count;
for (uint256 i = 0; i < names.length; i++) {
_names[count + i] = names[i];
}
_count = count + names.length;
}
uint256 _count;
mapping(uint256 => string) _names;
constructor(
address metaTransactionContract,
address admin,
address initialMinter,
string[] memory initialGems
) public MintableERC1155Token(metaTransactionContract, admin, initialMinter) {
_addGems(initialGems);
}
}
文件 15 的 76:ERC1155TokenReceiver.sol
pragma solidity ^0.6.0;
interface ERC1155TokenReceiver {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 16 的 76:ERC1271.sol
pragma solidity ^0.6.0;
interface ERC1271 {
function isValidSignature(bytes calldata data, bytes calldata signature) external view returns (bytes4 magicValue);
}
文件 17 的 76:ERC1271Constants.sol
pragma solidity ^0.6.0;
contract ERC1271Constants {
bytes4 internal constant ERC1271_MAGICVALUE = 0x20c13b0b;
}
文件 18 的 76:ERC165.sol
pragma solidity ^0.6.0;
interface ERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 19 的 76:ERC1654.sol
pragma solidity ^0.6.0;
interface ERC1654 {
function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
}
文件 20 的 76:ERC1654Constants.sol
pragma solidity ^0.6.0;
contract ERC1654Constants {
bytes4 internal constant ERC1654_MAGICVALUE = 0x1626ba7e;
}
文件 21 的 76:ERC20.sol
pragma solidity ^0.6.0;
interface ERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256 supply);
function balanceOf(address who) external view returns (uint256 balance);
function transfer(address to, uint256 value) external returns (bool success);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool success);
function approve(address spender, uint256 value) external returns (bool success);
function allowance(address owner, address spender) external view returns (uint256 amount);
}
文件 22 的 76:ERC20BaseToken.sol
pragma solidity 0.6.5;
import "../../Interfaces/ERC20Extended.sol";
import "../../common/BaseWithStorage/SuperOperators.sol";
contract ERC20BaseToken is SuperOperators, ERC20, ERC20Extended {
bytes32 internal immutable _name;
bytes32 internal immutable _symbol;
uint256 internal _totalSupply;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
constructor(
string memory tokenName,
string memory tokenSymbol,
address admin
) internal {
require(bytes(tokenName).length > 0, "INVALID_NAME_REQUIRED");
require(bytes(tokenName).length <= 32, "INVALID_NAME_TOO_LONG");
_name = _firstBytes32(bytes(tokenName));
require(bytes(tokenSymbol).length > 0, "INVALID_SYMBOL_REQUIRED");
require(bytes(tokenSymbol).length <= 32, "INVALID_SYMBOL_TOO_LONG");
_symbol = _firstBytes32(bytes(tokenSymbol));
_admin = admin;
}
function name() external view returns (string memory) {
return string(abi.encodePacked(_name));
}
function symbol() external view returns (string memory) {
return string(abi.encodePacked(_symbol));
}
function totalSupply() external override view returns (uint256) {
return _totalSupply;
}
function balanceOf(address owner) external override view returns (uint256) {
return _balances[owner];
}
function allowance(address owner, address spender) external override view returns (uint256 remaining) {
return _allowances[owner][spender];
}
function decimals() external virtual pure returns (uint8) {
return uint8(18);
}
function transfer(address to, uint256 amount) external override returns (bool success) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) external override returns (bool success) {
if (msg.sender != from && !_superOperators[msg.sender]) {
uint256 currentAllowance = _allowances[from][msg.sender];
if (currentAllowance != ~uint256(0)) {
require(currentAllowance >= amount, "NOT_AUTHOIZED_ALLOWANCE");
_allowances[from][msg.sender] = currentAllowance - amount;
}
}
_transfer(from, to, amount);
return true;
}
function burn(uint256 amount) external override {
_burn(msg.sender, amount);
}
function burnFor(address from, uint256 amount) external override {
if (msg.sender != from && !_superOperators[msg.sender]) {
uint256 currentAllowance = _allowances[from][msg.sender];
if (currentAllowance != ~uint256(0)) {
require(currentAllowance >= amount, "NOT_AUTHOIZED_ALLOWANCE");
_allowances[from][msg.sender] = currentAllowance - amount;
}
}
_burn(from, amount);
}
function approve(address spender, uint256 amount) external override returns (bool success) {
_approveFor(msg.sender, spender, amount);
return true;
}
function approveFor(
address owner,
address spender,
uint256 amount
) public returns (bool success) {
require(msg.sender == owner || _superOperators[msg.sender], "NOT_AUTHORIZED");
_approveFor(owner, spender, amount);
return true;
}
function addAllowanceIfNeeded(
address owner,
address spender,
uint256 amountNeeded
) public returns (bool success) {
require(msg.sender == owner || _superOperators[msg.sender], "msg.sender != owner && !superOperator");
_addAllowanceIfNeeded(owner, spender, amountNeeded);
return true;
}
function _addAllowanceIfNeeded(
address owner,
address spender,
uint256 amountNeeded
) internal {
if (amountNeeded > 0 && !isSuperOperator(spender)) {
uint256 currentAllowance = _allowances[owner][spender];
if (currentAllowance < amountNeeded) {
_approveFor(owner, spender, amountNeeded);
}
}
}
function _approveFor(
address owner,
address spender,
uint256 amount
) internal {
require(owner != address(0) && spender != address(0), "Cannot approve with 0x0");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(
address from,
address to,
uint256 amount
) internal {
require(to != address(0), "Cannot send to 0x0");
uint256 currentBalance = _balances[from];
require(currentBalance >= amount, "not enough fund");
_balances[from] = currentBalance - amount;
_balances[to] += amount;
emit Transfer(from, to, amount);
}
function _mint(address to, uint256 amount) internal {
require(to != address(0), "Cannot mint to 0x0");
require(amount > 0, "cannot mint 0 tokens");
uint256 currentTotalSupply = _totalSupply;
uint256 newTotalSupply = currentTotalSupply + amount;
require(newTotalSupply > currentTotalSupply, "overflow");
_totalSupply = newTotalSupply;
_balances[to] += amount;
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal {
require(amount > 0, "cannot burn 0 tokens");
if (msg.sender != from && !_superOperators[msg.sender]) {
uint256 currentAllowance = _allowances[from][msg.sender];
require(currentAllowance >= amount, "Not enough funds allowed");
if (currentAllowance != ~uint256(0)) {
_allowances[from][msg.sender] = currentAllowance - amount;
}
}
uint256 currentBalance = _balances[from];
require(currentBalance >= amount, "Not enough funds");
_balances[from] = currentBalance - amount;
_totalSupply -= amount;
emit Transfer(from, address(0), amount);
}
function _firstBytes32(bytes memory src) public pure returns (bytes32 output) {
assembly {
output := mload(add(src, 32))
}
}
}
文件 23 的 76:ERC20Extended.sol
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;
}
文件 24 的 76:ERC20Group.sol
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);
event SubToken(ERC20SubToken subToken);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event Minter(address minter, bool enabled);
function setMinter(address minter, bool enabled) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_setMinter(minter, enabled);
}
function isMinter(address who) public view returns (bool) {
return _minters[who];
}
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);
}
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;
}
}
function supplyOf(uint256 id) external view returns (uint256 supply) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
return _packedSupplies[bin].getValueInBin(index);
}
function balanceOf(address owner, uint256 id) public view returns (uint256 balance) {
(uint256 bin, uint256 index) = id.getTokenBinIndex();
return _packedTokenBalance[owner][bin].getValueInBin(index);
}
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]);
}
}
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);
}
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;
}
}
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);
}
function setApprovalForAll(address operator, bool approved) external {
_setApprovalForAll(msg.sender, operator, approved);
}
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);
}
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);
}
function burn(uint256 id, uint256 value) external {
_burn(msg.sender, id, value);
}
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);
}
using AddressUtils for address;
using ObjectLib32 for ObjectLib32.Operations;
using ObjectLib32 for uint256;
using SafeMath for uint256;
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;
struct SubTokenData {
string name;
string symbol;
}
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) internal {
_admin = admin;
_setMetaTransactionProcessor(metaTransactionContract, true);
_setMinter(initialMinter, true);
}
}
文件 25 的 76:ERC20GroupCatalyst.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../BaseWithStorage/ERC20Group.sol";
import "./CatalystDataBase.sol";
import "../BaseWithStorage/ERC20SubToken.sol";
import "./CatalystValue.sol";
contract ERC20GroupCatalyst is CatalystDataBase, ERC20Group {
function addCatalysts(
ERC20SubToken[] memory catalysts,
MintData[] memory mintData,
CatalystValue[] memory valueOverrides
) public {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
require(catalysts.length == mintData.length, "INVALID_INCONSISTENT_LENGTH");
for (uint256 i = 0; i < mintData.length; i++) {
uint256 id = _addSubToken(catalysts[i]);
_setMintData(id, mintData[i]);
if (valueOverrides.length > i) {
_setValueOverride(id, valueOverrides[i]);
}
}
}
function addCatalyst(
ERC20SubToken catalyst,
MintData memory mintData,
CatalystValue valueOverride
) public {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
uint256 id = _addSubToken(catalyst);
_setMintData(id, mintData);
_setValueOverride(id, valueOverride);
}
function setConfiguration(
uint256 id,
uint16 minQuantity,
uint16 maxQuantity,
uint256 sandMintingFee,
uint256 sandUpdateFee
) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
_setConfiguration(id, minQuantity, maxQuantity, sandMintingFee, sandUpdateFee);
}
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) public ERC20Group(metaTransactionContract, admin, initialMinter) {}
}
文件 26 的 76:ERC20GroupGem.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../BaseWithStorage/ERC20Group.sol";
contract ERC20GroupGem is ERC20Group {
function addGems(ERC20SubToken[] calldata catalysts) external {
require(msg.sender == _admin, "NOT_AUTHORIZED_ADMIN");
for (uint256 i = 0; i < catalysts.length; i++) {
_addSubToken(catalysts[i]);
}
}
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) public ERC20Group(metaTransactionContract, admin, initialMinter) {}
}
文件 27 的 76:ERC20Receiver.sol
pragma solidity ^0.6.0;
interface ERC20Receiver {
function receiveApproval(
address _from,
uint256 _value,
address _tokenAddress,
bytes calldata _data
) external;
}
文件 28 的 76:ERC20SubToken.sol
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 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function groupTokenId() external view returns (uint256) {
return _index;
}
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)) {
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);
}
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);
}
using SafeMathWithRequire for uint256;
constructor(
ERC20Group group,
uint256 index,
string memory tokenName,
string memory tokenSymbol
) public {
_group = group;
_index = index;
_name = tokenName;
_symbol = tokenSymbol;
}
ERC20Group internal immutable _group;
uint256 internal immutable _index;
mapping(address => mapping(address => uint256)) internal _mAllowed;
string internal _name;
string internal _symbol;
}
文件 29 的 76:ERC20WithMetadata.sol
pragma solidity ^0.6.0;
import "./ERC20.sol";
interface ERC20WithMetadata is ERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 30 的 76:ERC721.sol
pragma solidity ^0.6.0;
import "./ERC165.sol";
import "./ERC721Events.sol";
interface ERC721 is ERC165, ERC721Events {
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 31 的 76:ERC721BaseToken.sol
pragma solidity 0.6.5;
import "../common/Libraries/AddressUtils.sol";
import "../common/Interfaces/ERC721TokenReceiver.sol";
import "../common/Interfaces/ERC721Events.sol";
import "../common/BaseWithStorage/SuperOperators.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../common/Interfaces/ERC721MandatoryTokenReceiver.sol";
contract ERC721BaseToken is ERC721Events, SuperOperators, MetaTransactionReceiver {
using AddressUtils for address;
bytes4 internal constant _ERC721_RECEIVED = 0x150b7a02;
bytes4 internal constant _ERC721_BATCH_RECEIVED = 0x4b808c46;
bytes4 internal constant ERC165ID = 0x01ffc9a7;
bytes4 internal constant ERC721_MANDATORY_RECEIVER = 0x5e8bf644;
mapping(address => uint256) public _numNFTPerAddress;
mapping(uint256 => uint256) public _owners;
mapping(address => mapping(address => bool)) public _operatorsForAll;
mapping(uint256 => address) public _operators;
constructor(address metaTransactionContract, address admin) internal {
_admin = admin;
_setMetaTransactionProcessor(metaTransactionContract, true);
}
function _transferFrom(
address from,
address to,
uint256 id
) internal {
_numNFTPerAddress[from]--;
_numNFTPerAddress[to]++;
_owners[id] = uint256(to);
emit Transfer(from, to, id);
}
function balanceOf(address owner) external view returns (uint256) {
require(owner != address(0), "owner is zero address");
return _numNFTPerAddress[owner];
}
function _ownerOf(uint256 id) internal virtual view returns (address) {
uint256 data = _owners[id];
if ((data & (2**160)) == 2**160) {
return address(0);
}
return address(data);
}
function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
uint256 data = _owners[id];
if ((data & (2**160)) == 2**160) {
owner = address(0);
} else {
owner = address(data);
}
operatorEnabled = (data / 2**255) == 1;
}
function ownerOf(uint256 id) external view returns (address owner) {
owner = _ownerOf(id);
require(owner != address(0), "token does not exist");
}
function _approveFor(
address owner,
address operator,
uint256 id
) internal {
if (operator == address(0)) {
_owners[id] = _owners[id] & (2**255 - 1);
} else {
_owners[id] = _owners[id] | (2**255);
_operators[id] = operator;
}
emit Approval(owner, operator, id);
}
function approveFor(
address sender,
address operator,
uint256 id
) external {
address owner = _ownerOf(id);
require(sender != address(0), "sender is zero address");
require(
msg.sender == sender || _metaTransactionContracts[msg.sender] || _superOperators[msg.sender] || _operatorsForAll[sender][msg.sender],
"not authorized to approve"
);
require(owner == sender, "owner != sender");
_approveFor(owner, operator, id);
}
function approve(address operator, uint256 id) external {
address owner = _ownerOf(id);
require(owner != address(0), "token does not exist");
require(owner == msg.sender || _superOperators[msg.sender] || _operatorsForAll[owner][msg.sender], "not authorized to approve");
_approveFor(owner, operator, id);
}
function getApproved(uint256 id) external view returns (address) {
(address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
require(owner != address(0), "token does not exist");
if (operatorEnabled) {
return _operators[id];
} else {
return address(0);
}
}
function _checkTransfer(
address from,
address to,
uint256 id
) internal view returns (bool isMetaTx) {
(address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
require(owner != address(0), "token does not exist");
require(owner == from, "not owner in _checkTransfer");
require(to != address(0), "can't send to zero address");
isMetaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
if (msg.sender != from && !isMetaTx) {
require(
_superOperators[msg.sender] || _operatorsForAll[from][msg.sender] || (operatorEnabled && _operators[id] == msg.sender),
"not approved to transfer"
);
}
}
function _checkInterfaceWith10000Gas(address _contract, bytes4 interfaceId) internal view returns (bool) {
bool success;
bool result;
bytes memory call_data = abi.encodeWithSelector(ERC165ID, interfaceId);
assembly {
let call_ptr := add(0x20, call_data)
let call_size := mload(call_data)
let output := mload(0x40)
mstore(output, 0x0)
success := staticcall(10000, _contract, call_ptr, call_size, output, 0x20)
result := mload(output)
}
assert(gasleft() > 158);
return success && result;
}
function transferFrom(
address from,
address to,
uint256 id
) external {
bool metaTx = _checkTransfer(from, to, id);
_transferFrom(from, to, id);
if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
require(_checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, ""), "erc721 transfer rejected by to");
}
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes memory data
) public {
bool metaTx = _checkTransfer(from, to, id);
_transferFrom(from, to, id);
if (to.isContract()) {
require(_checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, data), "ERC721: transfer rejected by to");
}
}
function safeTransferFrom(
address from,
address to,
uint256 id
) external {
safeTransferFrom(from, to, id, "");
}
function batchTransferFrom(
address from,
address to,
uint256[] calldata ids,
bytes calldata data
) external {
_batchTransferFrom(from, to, ids, data, false);
}
function _batchTransferFrom(
address from,
address to,
uint256[] memory ids,
bytes memory data,
bool safe
) internal {
bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
bool authorized = msg.sender == from || metaTx || _superOperators[msg.sender] || _operatorsForAll[from][msg.sender];
require(from != address(0), "from is zero address");
require(to != address(0), "can't send to zero address");
uint256 numTokens = ids.length;
for (uint256 i = 0; i < numTokens; i++) {
uint256 id = ids[i];
(address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
require(owner == from, "not owner in batchTransferFrom");
require(authorized || (operatorEnabled && _operators[id] == msg.sender), "not authorized");
_owners[id] = uint256(to);
emit Transfer(from, to, id);
}
if (from != to) {
_numNFTPerAddress[from] -= numTokens;
_numNFTPerAddress[to] += numTokens;
}
if (to.isContract() && (safe || _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER))) {
require(_checkOnERC721BatchReceived(metaTx ? from : msg.sender, from, to, ids, data), "erc721 batch transfer rejected by to");
}
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
bytes calldata data
) external {
_batchTransferFrom(from, to, ids, data, true);
}
function supportsInterface(bytes4 id) public virtual pure returns (bool) {
return id == 0x01ffc9a7 || id == 0x80ac58cd;
}
function setApprovalForAllFor(
address sender,
address operator,
bool approved
) external {
require(sender != address(0), "Invalid sender address");
require(msg.sender == sender || _metaTransactionContracts[msg.sender] || _superOperators[msg.sender], "not authorized to approve for all");
_setApprovalForAll(sender, operator, approved);
}
function setApprovalForAll(address operator, bool approved) external {
_setApprovalForAll(msg.sender, operator, approved);
}
function _setApprovalForAll(
address sender,
address operator,
bool approved
) internal {
require(!_superOperators[operator], "super operator can't have their approvalForAll changed");
_operatorsForAll[sender][operator] = approved;
emit ApprovalForAll(sender, operator, approved);
}
function isApprovedForAll(address owner, address operator) external view returns (bool isOperator) {
return _operatorsForAll[owner][operator] || _superOperators[operator];
}
function _burn(
address from,
address owner,
uint256 id
) internal {
require(from == owner, "not owner");
_owners[id] = (_owners[id] & (2**255 - 1)) | (2**160);
_numNFTPerAddress[from]--;
emit Transfer(from, address(0), id);
}
function burn(uint256 id) external virtual {
_burn(msg.sender, _ownerOf(id), id);
}
function burnFrom(address from, uint256 id) external virtual {
require(from != address(0), "Invalid sender address");
(address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
require(
msg.sender == from ||
_metaTransactionContracts[msg.sender] ||
(operatorEnabled && _operators[id] == msg.sender) ||
_superOperators[msg.sender] ||
_operatorsForAll[from][msg.sender],
"not authorized to burn"
);
_burn(from, owner, id);
}
function _checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal returns (bool) {
bytes4 retval = ERC721TokenReceiver(to).onERC721Received(operator, from, tokenId, _data);
return (retval == _ERC721_RECEIVED);
}
function _checkOnERC721BatchReceived(
address operator,
address from,
address to,
uint256[] memory ids,
bytes memory _data
) internal returns (bool) {
bytes4 retval = ERC721MandatoryTokenReceiver(to).onERC721BatchReceived(operator, from, ids, _data);
return (retval == _ERC721_BATCH_RECEIVED);
}
}
文件 32 的 76:ERC721Events.sol
pragma solidity ^0.6.0;
interface ERC721Events {
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
}
文件 33 的 76:ERC721MandatoryTokenReceiver.sol
pragma solidity ^0.6.0;
interface ERC721MandatoryTokenReceiver {
function onERC721BatchReceived(
address operator,
address from,
uint256[] calldata ids,
bytes calldata data
) external returns (bytes4);
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 34 的 76:ERC721TokenReceiver.sol
pragma solidity ^0.6.0;
interface ERC721TokenReceiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 35 的 76:ERC777Token.sol
pragma solidity ^0.6.0;
interface ERC777Token {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function granularity() external view returns (uint256);
function defaultOperators() external view returns (address[] memory);
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
function authorizeOperator(address operator) external;
function revokeOperator(address operator) external;
function send(
address to,
uint256 amount,
bytes calldata data
) external;
function operatorSend(
address from,
address to,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData);
event Minted(address indexed operator, address indexed to, uint256 amount, bytes operatorData);
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
}
文件 36 的 76:ERC777TokenEvents.sol
pragma solidity ^0.6.0;
interface ERC777TokenEvents {
event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData);
event Minted(address indexed operator, address indexed to, uint256 amount, bytes operatorData);
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
}
文件 37 的 76:ERC777TokensRecipient.sol
pragma solidity ^0.6.0;
interface ERC777TokensRecipient {
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
}
文件 38 的 76:ERC777TokensSender.sol
pragma solidity ^0.6.0;
interface ERC777TokensSender {
function tokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}
文件 39 的 76:ERC820Implementer.sol
pragma solidity ^0.6.0;
interface ERC820Registry {
function getManager(address addr) external view returns (address);
function setManager(address addr, address newManager) external;
function getInterfaceImplementer(address addr, bytes32 iHash) external view returns (address);
function setInterfaceImplementer(
address addr,
bytes32 iHash,
address implementer
) external;
}
contract ERC820Implementer {
ERC820Registry constant erc820Registry = ERC820Registry(0x820b586C8C28125366C998641B09DCbE7d4cBF06);
function setInterfaceImplementation(string memory ifaceLabel, address impl) internal {
bytes32 ifaceHash = keccak256(bytes(ifaceLabel));
erc820Registry.setInterfaceImplementer(address(this), ifaceHash, impl);
}
function interfaceAddr(address addr, string memory ifaceLabel) internal view returns (address) {
bytes32 ifaceHash = keccak256(bytes(ifaceLabel));
return erc820Registry.getInterfaceImplementer(addr, ifaceHash);
}
function delegateManagement(address newManager) internal {
erc820Registry.setManager(address(this), newManager);
}
}
文件 40 的 76:EstateSaleWithFee.sol
pragma solidity 0.6.5;
import "../common/Libraries/SafeMathWithRequire.sol";
import "./LandToken.sol";
import "../common/Interfaces/ERC1155.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../ReferralValidator/ReferralValidator.sol";
contract EstateSaleWithFee is MetaTransactionReceiver, ReferralValidator {
using SafeMathWithRequire for uint256;
event LandQuadPurchased(
address indexed buyer,
address indexed to,
uint256 indexed topCornerId,
uint256 size,
uint256 price,
address token,
uint256 amountPaid
);
function setReceivingWallet(address payable newWallet) external {
require(newWallet != address(0), "ZERO_ADDRESS");
require(msg.sender == _admin, "NOT_AUTHORIZED");
_wallet = newWallet;
}
function rebalanceSand(uint256 newMultiplier) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
_multiplier = newMultiplier;
}
function getSandMultiplier() external view returns (uint256) {
return _multiplier;
}
function buyLandWithSand(
address buyer,
address to,
address reserved,
uint256 x,
uint256 y,
uint256 size,
uint256 priceInSand,
uint256 adjustedPriceInSand,
bytes32 salt,
uint256[] calldata assetIds,
bytes32[] calldata proof,
bytes calldata referral
) external {
_checkPrices(priceInSand, adjustedPriceInSand);
_checkValidity(buyer, reserved, x, y, size, priceInSand, salt, assetIds, proof);
_handleFeeAndReferral(buyer, adjustedPriceInSand, referral);
_mint(buyer, to, x, y, size, adjustedPriceInSand, address(_sand), adjustedPriceInSand);
_sendAssets(to, assetIds);
}
function getExpiryTime() external view returns (uint256) {
return _expiryTime;
}
function getMerkleRoot() external view returns (bytes32) {
return _merkleRoot;
}
function withdrawAssets(
address to,
uint256[] calldata assetIds,
uint256[] calldata values
) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
require(block.timestamp > _expiryTime, "SALE_NOT_OVER");
_asset.safeBatchTransferFrom(address(this), to, assetIds, values, "");
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external pure returns (bytes4) {
return 0xf23a6e61;
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external pure returns (bytes4) {
return 0xbc197c81;
}
function _sendAssets(address to, uint256[] memory assetIds) internal {
uint256[] memory values = new uint256[](assetIds.length);
for (uint256 i = 0; i < assetIds.length; i++) {
values[i] = 1;
}
_asset.safeBatchTransferFrom(address(this), to, assetIds, values, "");
}
function _checkPrices(uint256 priceInSand, uint256 adjustedPriceInSand) internal view {
require(adjustedPriceInSand == priceInSand.mul(_multiplier).div(MULTIPLIER_DECIMALS), "INVALID_PRICE");
}
function _checkValidity(
address buyer,
address reserved,
uint256 x,
uint256 y,
uint256 size,
uint256 price,
bytes32 salt,
uint256[] memory assetIds,
bytes32[] memory proof
) internal view {
require(block.timestamp < _expiryTime, "SALE_IS_OVER");
require(buyer == msg.sender || _metaTransactionContracts[msg.sender], "NOT_AUTHORIZED");
require(reserved == address(0) || reserved == buyer, "RESERVED_LAND");
bytes32 leaf = _generateLandHash(x, y, size, price, reserved, salt, assetIds);
require(_verify(proof, leaf), "INVALID_LAND");
}
function _mint(
address buyer,
address to,
uint256 x,
uint256 y,
uint256 size,
uint256 price,
address token,
uint256 tokenAmount
) internal {
if (size == 1 || _estate == address(0)) {
_land.mintQuad(to, size, x, y, "");
} else {
_land.mintQuad(_estate, size, x, y, abi.encode(to));
}
emit LandQuadPurchased(buyer, to, x + (y * GRID_SIZE), size, price, token, tokenAmount);
}
function _generateLandHash(
uint256 x,
uint256 y,
uint256 size,
uint256 price,
address reserved,
bytes32 salt,
uint256[] memory assetIds
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(x, y, size, price, reserved, salt, assetIds));
}
function _verify(bytes32[] memory proof, bytes32 leaf) internal view returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash < proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == _merkleRoot;
}
function _handleFeeAndReferral(
address buyer,
uint256 priceInSand,
bytes memory referral
) internal {
uint256 remainingAmountInSand = _handleSandFee(buyer, priceInSand);
handleReferralWithERC20(buyer, remainingAmountInSand, referral, _wallet, address(_sand));
}
function _handleSandFee(address buyer, uint256 priceInSand) internal returns (uint256) {
uint256 feeAmountInSand = priceInSand.mul(FEE).div(100);
require(_sand.transferFrom(buyer, address(_feeDistributor), feeAmountInSand), "FEE_TRANSFER_FAILED");
return priceInSand.sub(feeAmountInSand);
}
uint256 internal constant GRID_SIZE = 408;
ERC1155 internal immutable _asset;
LandToken internal immutable _land;
ERC20 internal immutable _sand;
address internal immutable _estate;
address internal immutable _feeDistributor;
address payable internal _wallet;
uint256 internal immutable _expiryTime;
bytes32 internal immutable _merkleRoot;
uint256 private constant FEE = 5;
uint256 private _multiplier = 1000;
uint256 private constant MULTIPLIER_DECIMALS = 1000;
constructor(
address landAddress,
address sandContractAddress,
address initialMetaTx,
address admin,
address payable initialWalletAddress,
bytes32 merkleRoot,
uint256 expiryTime,
address initialSigningWallet,
uint256 initialMaxCommissionRate,
address estate,
address asset,
address feeDistributor
) public ReferralValidator(initialSigningWallet, initialMaxCommissionRate) {
_land = LandToken(landAddress);
_sand = ERC20(sandContractAddress);
_setMetaTransactionProcessor(initialMetaTx, true);
_wallet = initialWalletAddress;
_merkleRoot = merkleRoot;
_expiryTime = expiryTime;
_admin = admin;
_estate = estate;
_asset = ERC1155(asset);
_feeDistributor = feeDistributor;
}
}
文件 41 的 76:FeeDistributor.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../common/interfaces/ERC20.sol";
import "../common/Libraries/SafeMathWithRequire.sol";
contract FeeDistributor {
event Deposit(address token, address from, uint256 amount);
event Withdrawal(ERC20 token, address to, uint256 amount);
mapping(address => uint256) public recipientsShares;
function withdraw(ERC20 token) external returns (uint256 amount) {
if (address(token) == address(0)) {
amount = _etherWithdrawal();
} else {
amount = _tokenWithdrawal(token);
}
if (amount != 0) {
emit Withdrawal(token, msg.sender, amount);
}
}
receive() external payable {
emit Deposit(address(0), msg.sender, msg.value);
}
function _etherWithdrawal() private returns (uint256) {
uint256 amount = _calculateWithdrawalAmount(address(this).balance, address(0));
if (amount != 0) {
msg.sender.transfer(amount);
}
return amount;
}
function _tokenWithdrawal(ERC20 token) private returns (uint256) {
uint256 amount = _calculateWithdrawalAmount(ERC20(token).balanceOf(address(this)), address(token));
if (amount != 0) {
require(ERC20(token).transfer(msg.sender, amount), "FEE_WITHDRAWAL_FAILED");
}
return amount;
}
function _calculateWithdrawalAmount(uint256 currentBalance, address token) private returns (uint256) {
uint256 totalReceived = _tokensState[token].totalReceived;
uint256 lastBalance = _tokensState[token].lastBalance;
uint256 amountAlreadyGiven = _tokensState[token].amountAlreadyGiven[msg.sender];
uint256 _currentBalance = currentBalance;
totalReceived = totalReceived.add(_currentBalance.sub(lastBalance));
_tokensState[token].totalReceived = totalReceived;
uint256 amountDue = ((totalReceived.mul(recipientsShares[msg.sender])).div(10**DECIMALS)).sub(amountAlreadyGiven);
if (amountDue == 0) {
return amountDue;
}
amountAlreadyGiven = amountAlreadyGiven.add(amountDue);
_tokensState[token].amountAlreadyGiven[msg.sender] = amountAlreadyGiven;
_tokensState[token].lastBalance = _currentBalance.sub(amountDue);
return amountDue;
}
using SafeMathWithRequire for uint256;
struct TokenState {
uint256 totalReceived;
mapping(address => uint256) amountAlreadyGiven;
uint256 lastBalance;
}
mapping(address => TokenState) private _tokensState;
uint256 private constant DECIMALS = 4;
constructor(address payable[] memory recipients, uint256[] memory percentages) public {
require(recipients.length == percentages.length, "ARRAYS_LENGTHS_SHOULD_BE_EQUAL");
uint256 totalPercentage = 0;
for (uint256 i = 0; i < recipients.length; i++) {
uint256 percentage = percentages[i];
recipientsShares[recipients[i]] = percentage;
totalPercentage = totalPercentage.add(percentage);
}
require(totalPercentage == 10**DECIMALS, "PERCENTAGES_ARRAY_SHOULD_SUM_TO_100%");
}
}
文件 42 的 76:Foundation.sol
pragma solidity ^0.6.5;
contract Foundation {}
文件 43 的 76:FoundationDAI.sol
pragma solidity ^0.6.5;
contract FoundationDAI {}
文件 44 的 76:GemToken.sol
pragma solidity 0.6.5;
interface GemToken {
function batchBurnFrom(
address from,
uint256[] calldata ids,
uint256[] calldata amounts
) external;
}
文件 45 的 76:LandToken.sol
pragma solidity 0.6.5;
interface LandToken {
function batchTransferQuad(
address from,
address to,
uint256[] calldata sizes,
uint256[] calldata xs,
uint256[] calldata ys,
bytes calldata data
) external;
function transferQuad(
address from,
address to,
uint256 size,
uint256 x,
uint256 y,
bytes calldata data
) external;
function batchTransferFrom(
address from,
address to,
uint256[] calldata ids,
bytes calldata data
) external;
function transferFrom(
address from,
address to,
uint256 id
) external;
}
文件 46 的 76:Math.sol
pragma solidity ^0.6.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256 c) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256 c) {
return a < b ? a : b;
}
}
文件 47 的 76:Medianizer.sol
pragma solidity ^0.6.0;
interface Medianizer {
function read() external view returns (bytes32);
}
文件 48 的 76:MetaTransactionReceiver.sol
pragma solidity ^0.6.0;
import "./Admin.sol";
contract MetaTransactionReceiver is Admin {
mapping(address => bool) internal _metaTransactionContracts;
event MetaTransactionProcessor(address metaTransactionProcessor, bool enabled);
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);
}
function isMetaTransactionProcessor(address who) external view returns (bool) {
return _metaTransactionContracts[who];
}
}
文件 49 的 76:MetaTxWrapper.sol
pragma solidity 0.6.5;
contract MetaTxWrapper {
address internal immutable _forwardTo;
address internal immutable _forwarder;
constructor(address forwarder, address forwardTo) public {
_forwardTo = forwardTo;
_forwarder = forwarder;
}
fallback() external {
require(msg.sender == _forwarder, "can only be called by a forwarder");
bytes memory data = msg.data;
uint256 length = msg.data.length;
address signer;
assembly {
signer := and(mload(sub(add(data, length), 0x00)), 0xffffffffffffffffffffffffffffffffffffffff)
}
uint256 firstParam;
assembly {
firstParam := and(mload(data), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
}
require(uint256(signer) == firstParam, "firstParam is not signer");
}
}
文件 50 的 76:MintableERC1155Token.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "./ERC1155BaseToken.sol";
contract MintableERC1155Token is ERC1155BaseToken {
event Minter(address minter, bool enabled);
function setMinter(address minter, bool enabled) external {
require(msg.sender == _admin, "only admin is allowed to add minters");
_setMinter(minter, enabled);
}
function isMinter(address who) public view returns (bool) {
return _minters[who];
}
function mint(
address to,
uint256 id,
uint256 amount
) external {
require(_minters[msg.sender], "only minter allowed to mint");
(uint256 bin, uint256 index) = id.getTokenBinIndex();
_packedTokenBalance[to][bin] = ObjectLib32.updateTokenBalance(_packedTokenBalance[to][bin], index, amount, ObjectLib32.Operations.ADD);
emit TransferSingle(msg.sender, address(0), to, id, amount);
}
function batchMint(
address to,
uint256[] calldata ids,
uint256[] calldata amounts
) external {
require(_minters[msg.sender], "only minter allowed to mint");
require(to != address(0), "to is zero address");
uint256 balTo;
uint256 lastBin = ~uint256(0);
for (uint256 i = 0; i < ids.length; i++) {
if (amounts[i] > 0) {
(uint256 bin, uint256 index) = ids[i].getTokenBinIndex();
if (lastBin == ~uint256(0)) {
lastBin = bin;
balTo = ObjectLib32.updateTokenBalance(_packedTokenBalance[to][bin], index, amounts[i], ObjectLib32.Operations.ADD);
} else {
if (bin != lastBin) {
_packedTokenBalance[to][lastBin] = balTo;
balTo = _packedTokenBalance[to][bin];
lastBin = bin;
}
balTo = balTo.updateTokenBalance(index, amounts[i], ObjectLib32.Operations.ADD);
}
}
}
if (lastBin != ~uint256(0)) {
_packedTokenBalance[to][lastBin] = balTo;
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
}
function _setMinter(address minter, bool enabled) internal {
_minters[minter] = enabled;
emit Minter(minter, enabled);
}
mapping(address => bool) internal _minters;
constructor(
address metaTransactionContract,
address admin,
address initialMinter
) internal ERC1155BaseToken(metaTransactionContract, admin) {
_setMinter(initialMinter, true);
}
}
文件 51 的 76:MockERC20.sol
pragma solidity ^0.6.5;
import "../common/Libraries/SafeMathWithRequire.sol";
import "../common/BaseWithStorage/Ownable.sol";
import "../common/interfaces/ERC20.sol";
contract ERC20Impl is ERC20 {
using SafeMathWithRequire for uint256;
mapping(address => uint256) public _balances;
mapping(address => mapping(address => uint256)) public _allowances;
uint256 public _totalSupply;
function totalSupply() public override view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public override view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner, address spender) public override view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount);
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
contract MintableToken is ERC20Impl, Ownable {
function mint(address account, uint256 amount) public onlyOwner {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
}
contract MockERC20 is MintableToken {
string public constant name = "Mock Token";
string public constant symbol = "MCK";
uint8 public constant decimals = 18;
}
文件 52 的 76:ObjectLib.sol
pragma solidity ^0.6.0;
import "./SafeMathWithRequire.sol";
library ObjectLib {
using SafeMathWithRequire for uint256;
enum Operations {ADD, SUB, REPLACE}
uint256 constant TYPES_BITS_SIZE = 16;
uint256 constant TYPES_PER_UINT256 = 256 / TYPES_BITS_SIZE;
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);
}
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);
newBinBalance = writeValueInBin(_binBalances, _index, objectBalance.sub(_amount));
} else if (_operation == Operations.REPLACE) {
newBinBalance = writeValueInBin(_binBalances, _index, _amount);
} else {
revert("Invalid operation");
}
return newBinBalance;
}
function getValueInBin(uint256 _binValue, uint256 _index) internal pure returns (uint256) {
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 rightShift = 256 - TYPES_BITS_SIZE * (_index + 1);
return (_binValue >> rightShift) & mask;
}
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");
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 leftShift = 256 - TYPES_BITS_SIZE * (_index + 1);
return (_binValue & ~(mask << leftShift)) | (_amount << leftShift);
}
}
文件 53 的 76:ObjectLib32.sol
pragma solidity ^0.6.0;
import "./SafeMathWithRequire.sol";
library ObjectLib32 {
using SafeMathWithRequire for uint256;
enum Operations {ADD, SUB, REPLACE}
uint256 constant TYPES_BITS_SIZE = 32;
uint256 constant TYPES_PER_UINT256 = 256 / TYPES_BITS_SIZE;
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);
}
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");
}
return newBinBalance;
}
function getValueInBin(uint256 binValue, uint256 index) internal pure returns (uint256) {
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 rightShift = 256 - TYPES_BITS_SIZE * (index + 1);
return (binValue >> rightShift) & mask;
}
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");
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 leftShift = 256 - TYPES_BITS_SIZE * (index + 1);
return (binValue & ~(mask << leftShift)) | (amount << leftShift);
}
}
文件 54 的 76:ObjectLib64.sol
pragma solidity ^0.6.0;
import "./SafeMathWithRequire.sol";
library ObjectLib64 {
using SafeMathWithRequire for uint256;
enum Operations {ADD, SUB, REPLACE}
uint256 constant TYPES_BITS_SIZE = 64;
uint256 constant TYPES_PER_UINT256 = 256 / TYPES_BITS_SIZE;
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);
}
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);
newBinBalance = writeValueInBin(_binBalances, _index, objectBalance.sub(_amount));
} else if (_operation == Operations.REPLACE) {
newBinBalance = writeValueInBin(_binBalances, _index, _amount);
} else {
revert("Invalid operation");
}
return newBinBalance;
}
function getValueInBin(uint256 _binValue, uint256 _index) internal pure returns (uint256) {
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 rightShift = 256 - TYPES_BITS_SIZE * (_index + 1);
return (_binValue >> rightShift) & mask;
}
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");
uint256 mask = (uint256(1) << TYPES_BITS_SIZE) - 1;
uint256 leftShift = 256 - TYPES_BITS_SIZE * (_index + 1);
return (_binValue & ~(mask << leftShift)) | (_amount << leftShift);
}
}
文件 55 的 76:Ownable.sol
pragma solidity ^0.6.0;
contract Ownable {
address payable public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address payable _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
function _transferOwnership(address payable _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
文件 56 的 76:P2PERC721Sale.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../common/BaseWithStorage/Admin.sol";
import "../common/Libraries/SigUtil.sol";
import "../common/Libraries/PriceUtil.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../common/Interfaces/ERC721.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/Interfaces/ERC1271.sol";
import "../common/Interfaces/ERC1271Constants.sol";
import "../common/Interfaces/ERC1654.sol";
import "../common/Interfaces/ERC1654Constants.sol";
import "../common/Libraries/SafeMathWithRequire.sol";
import "../Base/TheSandbox712.sol";
contract P2PERC721Sale is Admin, ERC1654Constants, ERC1271Constants, TheSandbox712, MetaTransactionReceiver {
using SafeMathWithRequire for uint256;
enum SignatureType {DIRECT, EIP1654, EIP1271}
mapping(address => mapping(uint256 => uint256)) public claimed;
uint256 private constant MAX_UINT256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
ERC20 internal _sand;
uint256 internal _fee;
address internal _feeCollector;
struct Auction {
uint256 id;
address tokenAddress;
uint256 tokenId;
address seller;
uint256 startingPrice;
uint256 endingPrice;
uint256 startedAt;
uint256 duration;
}
event OfferClaimed(
address indexed seller,
address indexed buyer,
uint256 indexed offerId,
address tokenAddress,
uint256 tokenId,
uint256 pricePaid,
uint256 feePaid
);
event OfferCancelled(address indexed seller, uint256 indexed offerId);
event FeeSetup(address feeCollector, uint256 fee10000th);
constructor(
address sand,
address admin,
address feeCollector,
uint256 fee,
address initialMetaTx
) public {
_sand = ERC20(sand);
_admin = admin;
_fee = fee;
_feeCollector = feeCollector;
emit FeeSetup(feeCollector, fee);
_setMetaTransactionProcessor(initialMetaTx, true);
init712();
}
function setFee(address feeCollector, uint256 fee) external {
require(msg.sender == _admin, "Sender not admin");
_feeCollector = feeCollector;
_fee = fee;
emit FeeSetup(feeCollector, fee);
}
function _verifyParameters(address buyer, Auction memory auction) internal view {
require(buyer == msg.sender || _metaTransactionContracts[msg.sender], "not authorized");
require(claimed[auction.seller][auction.id] != MAX_UINT256, "Auction canceled");
require(auction.startedAt <= now, "Auction has not started yet");
require(auction.startedAt.add(auction.duration) > now, "Auction finished");
}
function claimSellerOffer(
address buyer,
address to,
Auction calldata auction,
bytes calldata signature,
SignatureType signatureType,
bool eip712
) external {
_verifyParameters(buyer, auction);
_ensureCorrectSigner(auction, signature, signatureType, eip712);
_executeDeal(auction, buyer, to);
}
function _executeDeal(
Auction memory auction,
address buyer,
address to
) internal {
uint256 offer = PriceUtil.calculateCurrentPrice(auction.startingPrice, auction.endingPrice, auction.duration, now.sub(auction.startedAt));
claimed[auction.seller][auction.id] = offer;
uint256 fee = 0;
if (_fee > 0) {
fee = PriceUtil.calculateFee(offer, _fee);
}
require(_sand.transferFrom(buyer, auction.seller, offer.sub(fee)), "Funds transfer failed");
ERC721 token = ERC721(auction.tokenAddress);
token.safeTransferFrom(auction.seller, to, auction.tokenId);
}
function cancelSellerOffer(uint256 id) external {
claimed[msg.sender][id] = MAX_UINT256;
emit OfferCancelled(msg.sender, id);
}
function _ensureCorrectSigner(
Auction memory auction,
bytes memory signature,
SignatureType signatureType,
bool eip712
) internal view returns (address) {
bytes memory dataToHash;
if (eip712) {
dataToHash = abi.encodePacked("\x19\x01", domainSeparator(), _hashAuction(auction));
} else {
dataToHash = _encodeBasicSignatureHash(auction);
}
if (signatureType == SignatureType.EIP1271) {
require(ERC1271(auction.seller).isValidSignature(dataToHash, signature) == ERC1271_MAGICVALUE, "Invalid 1271 sig");
} else if (signatureType == SignatureType.EIP1654) {
require(ERC1654(auction.seller).isValidSignature(keccak256(dataToHash), signature) == ERC1654_MAGICVALUE, "Invalid 1654 sig");
} else {
address signer = SigUtil.recover(keccak256(dataToHash), signature);
require(signer == auction.seller, "Invalid sig");
}
}
function _encodeBasicSignatureHash(Auction memory auction) internal view returns (bytes memory) {
return
SigUtil.prefixed(
keccak256(
abi.encodePacked(
address(this),
auction.id,
auction.tokenAddress,
auction.tokenId,
auction.seller,
auction.startingPrice,
auction.endingPrice,
auction.startedAt,
auction.duration
)
)
);
}
function _hashAuction(Auction memory auction) internal pure returns (bytes32) {
return
keccak256(
abi.encode(
auction.id,
auction.tokenAddress,
auction.tokenId,
auction.seller,
auction.startingPrice,
auction.endingPrice,
auction.startedAt,
auction.duration
)
);
}
}
文件 57 的 76:Pausable.sol
pragma solidity ^0.6.0;
import "./Ownable.sol";
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
modifier whenNotPaused() {
require(!paused);
_;
}
modifier whenPaused() {
require(paused);
_;
}
function pause() public onlyOwner whenNotPaused {
paused = true;
emit Pause();
}
function unpause() public onlyOwner whenPaused {
paused = false;
emit Unpause();
}
}
文件 58 的 76:PriceUtil.sol
pragma solidity ^0.6.0;
import "./SafeMathWithRequire.sol";
library PriceUtil {
using SafeMathWithRequire for uint256;
function calculateCurrentPrice(
uint256 startingPrice,
uint256 endingPrice,
uint256 duration,
uint256 secondsPassed
) internal pure returns (uint256) {
if (secondsPassed > duration) {
return endingPrice;
}
if (endingPrice == startingPrice) {
return endingPrice;
} else if (endingPrice > startingPrice) {
return startingPrice.add((endingPrice.sub(startingPrice)).mul(secondsPassed).div(duration));
} else {
return startingPrice.sub((startingPrice.sub(endingPrice)).mul(secondsPassed).div(duration));
}
}
function calculateFee(uint256 price, uint256 fee10000th) internal pure returns (uint256) {
return (price.mul(fee10000th)) / 10000;
}
}
文件 59 的 76:ProxyAdmin.sol
pragma solidity ^0.6.0;
import "./AdminUpgradeabilityProxy.sol";
import "../BaseWithStorage/Ownable.sol";
contract ProxyAdmin is Ownable {
AdminUpgradeabilityProxy proxy;
constructor(AdminUpgradeabilityProxy _proxy, address payable _owner) public {
proxy = _proxy;
owner = _owner;
}
function proxyAddress() public view returns (address) {
return address(proxy);
}
function admin() public returns (address) {
return proxy.admin();
}
function changeAdmin(address newAdmin) public onlyOwner {
proxy.changeAdmin(newAdmin);
}
function upgradeTo(address implementation) public onlyOwner {
proxy.upgradeTo(implementation);
}
function upgradeToAndCall(address implementation, bytes memory data) public payable onlyOwner {
proxy.upgradeToAndCall{value:msg.value}(implementation, data);
}
}
文件 60 的 76:ProxyBase.sol
pragma solidity ^0.6.0;
abstract contract ProxyBase {
fallback() external payable {
_fallback();
}
receive() external payable {
_fallback();
}
function _implementation() internal virtual view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
function _willFallback() internal virtual {}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
文件 61 的 76:ProxyImplementation.sol
pragma solidity ^0.6.0;
contract ProxyImplementation {
mapping(string => bool) _initialised;
modifier phase(string memory phaseName) {
if (!_initialised[phaseName]) {
_initialised[phaseName] = true;
_;
}
}
}
文件 62 的 76:PurchaseValidator.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../common/Libraries/SigUtil.sol";
import "../common/BaseWithStorage/Admin.sol";
contract PurchaseValidator is Admin {
address private _signingWallet;
mapping(address => mapping(uint128 => uint128)) public queuedNonces;
function getNonceByBuyer(address _buyer, uint128 _queueId) external view returns (uint128) {
return queuedNonces[_buyer][_queueId];
}
function isPurchaseValid(
address buyer,
uint256[] memory catalystIds,
uint256[] memory catalystQuantities,
uint256[] memory gemIds,
uint256[] memory gemQuantities,
uint256 nonce,
bytes memory signature
) public returns (bool) {
require(_checkAndUpdateNonce(buyer, nonce), "INVALID_NONCE");
bytes32 hashedData = keccak256(abi.encodePacked(catalystIds, catalystQuantities, gemIds, gemQuantities, buyer, nonce));
address signer = SigUtil.recover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hashedData)), signature);
return signer == _signingWallet;
}
function getSigningWallet() external view returns (address) {
return _signingWallet;
}
function updateSigningWallet(address newSigningWallet) external {
require(_admin == msg.sender, "SENDER_NOT_ADMIN");
_signingWallet = newSigningWallet;
}
function _checkAndUpdateNonce(address _buyer, uint256 _packedValue) private returns (bool) {
uint128 queueId = uint128(_packedValue / 2**128);
uint128 nonce = uint128(_packedValue % 2**128);
uint128 currentNonce = queuedNonces[_buyer][queueId];
if (nonce == currentNonce) {
queuedNonces[_buyer][queueId] = currentNonce + 1;
return true;
}
return false;
}
constructor(address initialSigningWallet) public {
_signingWallet = initialSigningWallet;
}
}
文件 63 的 76:ReferrableSale.sol
pragma solidity ^0.6.0;
import "./Ownable.sol";
contract ReferrableSale is Ownable {
event DefaultReferralSet(uint256 percentage);
event CustomReferralSet(address indexed referrer, uint256 percentage);
uint256 public defaultReferralPercentage;
mapping(address => uint256) public customReferralPercentages;
function setDefaultReferral(uint256 _defaultReferralPercentage) public onlyOwner {
require(_defaultReferralPercentage < 10000, "Referral must be less than 100 percent");
require(_defaultReferralPercentage != defaultReferralPercentage, "New referral must be different from the previous");
defaultReferralPercentage = _defaultReferralPercentage;
emit DefaultReferralSet(_defaultReferralPercentage);
}
function setCustomReferral(address _referrer, uint256 _customReferralPercentage) public onlyOwner {
require(_customReferralPercentage < 10000, "Referral must be less than 100 percent");
require(_customReferralPercentage != customReferralPercentages[_referrer], "New referral must be different from the previous");
customReferralPercentages[_referrer] = _customReferralPercentage;
emit CustomReferralSet(_referrer, _customReferralPercentage);
}
}
文件 64 的 76:ReferralValidator.sol
pragma solidity 0.6.5;
import "../common/Libraries/SigUtil.sol";
import "../common/Libraries/SafeMathWithRequire.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/BaseWithStorage/Admin.sol";
contract ReferralValidator is Admin {
address private _signingWallet;
uint256 private _maxCommissionRate;
mapping(address => uint256) private _previousSigningWallets;
uint256 private _previousSigningDelay = 60 * 60 * 24 * 10;
event ReferralUsed(
address indexed referrer,
address indexed referee,
address indexed token,
uint256 amount,
uint256 commission,
uint256 commissionRate
);
constructor(address initialSigningWallet, uint256 initialMaxCommissionRate) public {
_signingWallet = initialSigningWallet;
_maxCommissionRate = initialMaxCommissionRate;
}
function updateSigningWallet(address newSigningWallet) external {
require(_admin == msg.sender, "Sender not admin");
_previousSigningWallets[_signingWallet] = now + _previousSigningDelay;
_signingWallet = newSigningWallet;
}
function getSigningWallet() external view returns (address) {
return _signingWallet;
}
function getMaxCommisionRate() external view returns (uint256) {
return _maxCommissionRate;
}
function updateMaxCommissionRate(uint256 newMaxCommissionRate) external {
require(_admin == msg.sender, "Sender not admin");
_maxCommissionRate = newMaxCommissionRate;
}
function handleReferralWithETH(
uint256 amount,
bytes memory referral,
address payable destination
) internal {
uint256 amountForDestination = amount;
if (referral.length > 0) {
(bytes memory signature, address referrer, address referee, uint256 expiryTime, uint256 commissionRate) = decodeReferral(referral);
uint256 commission = 0;
if (isReferralValid(signature, referrer, referee, expiryTime, commissionRate)) {
commission = SafeMathWithRequire.div(SafeMathWithRequire.mul(amount, commissionRate), 10000);
emit ReferralUsed(referrer, referee, address(0), amount, commission, commissionRate);
amountForDestination = SafeMathWithRequire.sub(amountForDestination, commission);
}
if (commission > 0) {
address(uint160(referrer)).transfer(commission);
}
}
destination.transfer(amountForDestination);
}
function handleReferralWithERC20(
address buyer,
uint256 amount,
bytes memory referral,
address payable destination,
address tokenAddress
) internal {
ERC20 token = ERC20(tokenAddress);
uint256 amountForDestination = amount;
if (referral.length > 0) {
(bytes memory signature, address referrer, address referee, uint256 expiryTime, uint256 commissionRate) = decodeReferral(referral);
uint256 commission = 0;
if (isReferralValid(signature, referrer, referee, expiryTime, commissionRate)) {
commission = SafeMathWithRequire.div(SafeMathWithRequire.mul(amount, commissionRate), 10000);
emit ReferralUsed(referrer, referee, tokenAddress, amount, commission, commissionRate);
amountForDestination = SafeMathWithRequire.sub(amountForDestination, commission);
}
if (commission > 0) {
require(token.transferFrom(buyer, referrer, commission), "commision transfer failed");
}
}
require(token.transferFrom(buyer, destination, amountForDestination), "payment transfer failed");
}
function isReferralValid(
bytes memory signature,
address referrer,
address referee,
uint256 expiryTime,
uint256 commissionRate
) public view returns (bool) {
if (commissionRate > _maxCommissionRate || referrer == referee || now > expiryTime) {
return false;
}
bytes32 hashedData = keccak256(abi.encodePacked(referrer, referee, expiryTime, commissionRate));
address signer = SigUtil.recover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hashedData)), signature);
if (_previousSigningWallets[signer] >= now) {
return true;
}
return _signingWallet == signer;
}
function decodeReferral(bytes memory referral)
public
pure
returns (
bytes memory,
address,
address,
uint256,
uint256
)
{
(bytes memory signature, address referrer, address referee, uint256 expiryTime, uint256 commissionRate) = abi.decode(
referral,
(bytes, address, address, uint256, uint256)
);
return (signature, referrer, referee, expiryTime, commissionRate);
}
}
文件 65 的 76:Reserve.sol
pragma solidity ^0.6.5;
contract Reserve {}
文件 66 的 76:SafeMath.sol
pragma solidity ^0.6.0;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
文件 67 的 76:SafeMathWithRequire.sol
pragma solidity ^0.6.0;
library SafeMathWithRequire {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
require(c / a == b, "overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "divbyzero");
return a / b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "undeflow");
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a, "overflow");
return c;
}
}
文件 68 的 76:SigUtil.sol
pragma solidity ^0.6.0;
library SigUtil {
function recover(bytes32 hash, bytes memory sig) internal pure returns (address recovered) {
require(sig.length == 65);
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
if (v < 27) {
v += 27;
}
require(v == 27 || v == 28);
recovered = ecrecover(hash, v, r, s);
require(recovered != address(0));
}
function recoverWithZeroOnFailure(bytes32 hash, bytes memory sig) internal pure returns (address) {
if (sig.length != 65) {
return (address(0));
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(hash, v, r, s);
}
}
function prefixed(bytes32 hash) internal pure returns (bytes memory) {
return abi.encodePacked("\x19Ethereum Signed Message:\n32", hash);
}
}
文件 69 的 76:StakingPool.sol
pragma solidity ^0.6.5;
contract StakingPool {}
文件 70 的 76:StarterPack.sol
pragma solidity 0.6.5;
interface StarterPack {
event Purchase(address indexed from, address indexed to, uint256[4] catQuantities, uint256[5] gemQuantities, uint256 priceInSand);
event SetPrices(uint256[4] prices);
function purchaseWithSand(
address from,
address to,
uint256[4] calldata catalystQuantities,
uint256[5] calldata gemQuantities,
uint256 nonce,
bytes calldata signature
) external payable;
function purchaseWithEth(
address from,
address to,
uint256[4] calldata catalystQuantities,
uint256[5] calldata gemQuantities,
uint256 nonce,
bytes calldata signature
) external payable;
function purchaseWithDai(
address from,
address to,
uint256[4] calldata catalystQuantities,
uint256[5] calldata gemQuantities,
uint256 nonce,
bytes calldata signature
) external payable;
function setPrices(uint256[4] calldata prices) external;
function withdrawAll(address to) external;
}
文件 71 的 76:StarterPackV1.sol
pragma solidity 0.6.5;
pragma experimental ABIEncoderV2;
import "../common/Libraries/SafeMathWithRequire.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../common/Interfaces/Medianizer.sol";
import "../common/BaseWithStorage/Admin.sol";
import "../Catalyst/ERC20GroupCatalyst.sol";
import "../Catalyst/ERC20GroupGem.sol";
import "./PurchaseValidator.sol";
contract StarterPackV1 is Admin, MetaTransactionReceiver, PurchaseValidator {
using SafeMathWithRequire for uint256;
uint256 internal constant DAI_PRICE = 55000000000000000;
ERC20 internal immutable _sand;
Medianizer private immutable _medianizer;
ERC20 private immutable _dai;
ERC20Group internal immutable _erc20GroupCatalyst;
ERC20Group internal immutable _erc20GroupGem;
bool _sandEnabled;
bool _etherEnabled;
bool _daiEnabled;
uint256[] private _starterPackPrices;
uint256[] private _previousStarterPackPrices;
uint256 private _gemPrice;
uint256 private _previousGemPrice;
uint256 private _priceChangeTimestamp;
address payable internal _wallet;
uint256 private _priceChangeDelay = 1 hours;
event Purchase(address indexed buyer, Message message, uint256 price, address token, uint256 amountPaid);
event SetPrices(uint256[] prices, uint256 gemPrice);
struct Message {
uint256[] catalystIds;
uint256[] catalystQuantities;
uint256[] gemIds;
uint256[] gemQuantities;
uint256 nonce;
}
function setReceivingWallet(address payable newWallet) external {
require(newWallet != address(0), "WALLET_ZERO_ADDRESS");
require(msg.sender == _admin, "NOT_AUTHORIZED");
_wallet = newWallet;
}
function setDAIEnabled(bool enabled) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
_daiEnabled = enabled;
}
function isDAIEnabled() external view returns (bool) {
return _daiEnabled;
}
function setETHEnabled(bool enabled) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
_etherEnabled = enabled;
}
function isETHEnabled() external view returns (bool) {
return _etherEnabled;
}
function setSANDEnabled(bool enabled) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
_sandEnabled = enabled;
}
function isSANDEnabled() external view returns (bool) {
return _sandEnabled;
}
function purchaseWithSand(
address buyer,
Message calldata message,
bytes calldata signature
) external {
require(msg.sender == buyer || _metaTransactionContracts[msg.sender], "INVALID_SENDER");
require(_sandEnabled, "SAND_IS_NOT_ENABLED");
require(buyer != address(0), "DESTINATION_ZERO_ADDRESS");
require(
isPurchaseValid(buyer, message.catalystIds, message.catalystQuantities, message.gemIds, message.gemQuantities, message.nonce, signature),
"INVALID_PURCHASE"
);
uint256 amountInSand = _calculateTotalPriceInSand(message.catalystIds, message.catalystQuantities, message.gemQuantities);
_handlePurchaseWithERC20(buyer, _wallet, address(_sand), amountInSand);
_erc20GroupCatalyst.batchTransferFrom(address(this), buyer, message.catalystIds, message.catalystQuantities);
_erc20GroupGem.batchTransferFrom(address(this), buyer, message.gemIds, message.gemQuantities);
emit Purchase(buyer, message, amountInSand, address(_sand), amountInSand);
}
function purchaseWithETH(
address buyer,
Message calldata message,
bytes calldata signature
) external payable {
require(msg.sender == buyer || _metaTransactionContracts[msg.sender], "INVALID_SENDER");
require(_etherEnabled, "ETHER_IS_NOT_ENABLED");
require(buyer != address(0), "DESTINATION_ZERO_ADDRESS");
require(buyer != address(this), "DESTINATION_STARTERPACKV1_CONTRACT");
require(
isPurchaseValid(buyer, message.catalystIds, message.catalystQuantities, message.gemIds, message.gemQuantities, message.nonce, signature),
"INVALID_PURCHASE"
);
uint256 amountInSand = _calculateTotalPriceInSand(message.catalystIds, message.catalystQuantities, message.gemQuantities);
uint256 ETHRequired = getEtherAmountWithSAND(amountInSand);
require(msg.value >= ETHRequired, "NOT_ENOUGH_ETHER_SENT");
_wallet.transfer(ETHRequired);
_erc20GroupCatalyst.batchTransferFrom(address(this), buyer, message.catalystIds, message.catalystQuantities);
_erc20GroupGem.batchTransferFrom(address(this), buyer, message.gemIds, message.gemQuantities);
emit Purchase(buyer, message, amountInSand, address(0), ETHRequired);
if (msg.value - ETHRequired > 0) {
msg.sender.transfer(msg.value - ETHRequired);
}
}
function purchaseWithDAI(
address buyer,
Message calldata message,
bytes calldata signature
) external {
require(msg.sender == buyer || _metaTransactionContracts[msg.sender], "INVALID_SENDER");
require(_daiEnabled, "DAI_IS_NOT_ENABLED");
require(buyer != address(0), "DESTINATION_ZERO_ADDRESS");
require(buyer != address(this), "DESTINATION_STARTERPACKV1_CONTRACT");
require(
isPurchaseValid(buyer, message.catalystIds, message.catalystQuantities, message.gemIds, message.gemQuantities, message.nonce, signature),
"INVALID_PURCHASE"
);
uint256 amountInSand = _calculateTotalPriceInSand(message.catalystIds, message.catalystQuantities, message.gemQuantities);
uint256 DAIRequired = amountInSand.mul(DAI_PRICE).div(1000000000000000000);
_handlePurchaseWithERC20(buyer, _wallet, address(_dai), DAIRequired);
_erc20GroupCatalyst.batchTransferFrom(address(this), buyer, message.catalystIds, message.catalystQuantities);
_erc20GroupGem.batchTransferFrom(address(this), buyer, message.gemIds, message.gemQuantities);
emit Purchase(buyer, message, amountInSand, address(_dai), DAIRequired);
}
function withdrawAll(
address to,
uint256[] calldata catalystIds,
uint256[] calldata gemIds
) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
address[] memory catalystAddresses = new address[](catalystIds.length);
for (uint256 i = 0; i < catalystIds.length; i++) {
catalystAddresses[i] = address(this);
}
address[] memory gemAddresses = new address[](gemIds.length);
for (uint256 i = 0; i < gemIds.length; i++) {
gemAddresses[i] = address(this);
}
uint256[] memory unsoldCatalystQuantities = _erc20GroupCatalyst.balanceOfBatch(catalystAddresses, catalystIds);
uint256[] memory unsoldGemQuantities = _erc20GroupGem.balanceOfBatch(gemAddresses, gemIds);
_erc20GroupCatalyst.batchTransferFrom(address(this), to, catalystIds, unsoldCatalystQuantities);
_erc20GroupGem.batchTransferFrom(address(this), to, gemIds, unsoldGemQuantities);
}
function setPrices(uint256[] calldata prices, uint256 gemPrice) external {
require(msg.sender == _admin, "NOT_AUTHORIZED");
_previousStarterPackPrices = _starterPackPrices;
_starterPackPrices = prices;
_previousGemPrice = _gemPrice;
_gemPrice = gemPrice;
_priceChangeTimestamp = now;
emit SetPrices(prices, gemPrice);
}
function getPrices()
external
view
returns (
uint256[] memory pricesBeforeSwitch,
uint256[] memory pricesAfterSwitch,
uint256 gemPriceBeforeSwitch,
uint256 gemPriceAfterSwitch,
uint256 switchTime
)
{
switchTime = 0;
if (_priceChangeTimestamp != 0) {
switchTime = _priceChangeTimestamp + _priceChangeDelay;
}
return (_previousStarterPackPrices, _starterPackPrices, _previousGemPrice, _gemPrice, switchTime);
}
function getEtherAmountWithSAND(uint256 sandAmount) public view returns (uint256) {
uint256 ethUsdPair = _getEthUsdPair();
return sandAmount.mul(DAI_PRICE).div(ethUsdPair);
}
function _getEthUsdPair() internal view returns (uint256) {
bytes32 pair = _medianizer.read();
return uint256(pair);
}
function _calculateTotalPriceInSand(
uint256[] memory catalystIds,
uint256[] memory catalystQuantities,
uint256[] memory gemQuantities
) internal returns (uint256) {
(uint256[] memory prices, uint256 gemPrice) = _priceSelector();
uint256 totalPrice;
for (uint256 i = 0; i < catalystIds.length; i++) {
uint256 id = catalystIds[i];
uint256 quantity = catalystQuantities[i];
totalPrice += prices[id].mul(quantity);
}
for (uint256 i = 0; i < gemQuantities.length; i++) {
uint256 quantity = gemQuantities[i];
totalPrice += gemPrice.mul(quantity);
}
return totalPrice;
}
function _priceSelector() internal returns (uint256[] memory, uint256) {
uint256[] memory prices;
uint256 gemPrice;
if (_priceChangeTimestamp == 0) {
prices = _starterPackPrices;
gemPrice = _gemPrice;
} else {
if (now > _priceChangeTimestamp + 1 hours) {
_priceChangeTimestamp = 0;
prices = _starterPackPrices;
gemPrice = _gemPrice;
} else {
prices = _previousStarterPackPrices;
gemPrice = _previousGemPrice;
}
}
return (prices, gemPrice);
}
function _handlePurchaseWithERC20(
address buyer,
address payable paymentRecipient,
address tokenAddress,
uint256 amount
) internal {
ERC20 token = ERC20(tokenAddress);
uint256 amountForDestination = amount;
require(token.transferFrom(buyer, paymentRecipient, amountForDestination), "PAYMENT_TRANSFER_FAILED");
}
constructor(
address starterPackAdmin,
address sandContractAddress,
address initialMetaTx,
address payable initialWalletAddress,
address medianizerContractAddress,
address daiTokenContractAddress,
address erc20GroupCatalystAddress,
address erc20GroupGemAddress,
address initialSigningWallet,
uint256[] memory initialStarterPackPrices,
uint256 initialGemPrice
) public PurchaseValidator(initialSigningWallet) {
_setMetaTransactionProcessor(initialMetaTx, true);
_wallet = initialWalletAddress;
_admin = starterPackAdmin;
_sand = ERC20(sandContractAddress);
_medianizer = Medianizer(medianizerContractAddress);
_dai = ERC20(daiTokenContractAddress);
_erc20GroupCatalyst = ERC20Group(erc20GroupCatalystAddress);
_erc20GroupGem = ERC20Group(erc20GroupGemAddress);
_starterPackPrices = initialStarterPackPrices;
_previousStarterPackPrices = initialStarterPackPrices;
_gemPrice = initialGemPrice;
_previousGemPrice = initialGemPrice;
_sandEnabled = true;
_etherEnabled = true;
}
}
文件 72 的 76:SuperOperators.sol
pragma solidity ^0.6.0;
import "./Admin.sol";
contract SuperOperators is Admin {
mapping(address => bool) internal _superOperators;
event SuperOperator(address superOperator, bool enabled);
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);
}
function isSuperOperator(address who) public view returns (bool) {
return _superOperators[who];
}
}
文件 73 的 76:TheSandbox712.sol
pragma solidity 0.6.5;
import {ProxyImplementation} from "../common/BaseWithStorage/ProxyImplementation.sol";
contract TheSandbox712 is ProxyImplementation {
bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,address verifyingContract)");
bytes32 DOMAIN_SEPARATOR;
function init712() public phase("712") {
DOMAIN_SEPARATOR = keccak256(abi.encode(EIP712DOMAIN_TYPEHASH, keccak256("The Sandbox 3D"), keccak256("1"), address(this)));
}
function domainSeparator() internal view returns (bytes32) {
return DOMAIN_SEPARATOR;
}
}
文件 74 的 76:Treasury.sol
pragma solidity ^0.6.5;
contract Treasury {}
文件 75 的 76:UpgradeabilityProxy.sol
pragma solidity ^0.6.0;
import "./ProxyBase.sol";
import "../Libraries/AddressUtils.sol";
contract UpgradeabilityProxy is ProxyBase {
event Upgraded(address indexed implementation);
bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
constructor(address _implementation, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
_setImplementation(_implementation);
if (_data.length > 0) {
(bool success, ) = _implementation.delegatecall(_data);
require(success, "could not call the contract");
}
}
function _implementation() override internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) private {
require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
文件 76 的 76:Withdrawable.sol
pragma solidity ^0.6.0;
import "./Ownable.sol";
import "../Interfaces/ERC20.sol";
contract Withdrawable is Ownable {
function withdrawEther(address payable _destination) external onlyOwner {
_destination.transfer(address(this).balance);
}
function withdrawToken(ERC20 _token, address _destination) external onlyOwner {
require(_token.transfer(_destination, _token.balanceOf(address(this))), "Transfer failed");
}
}
{
"compilationTarget": {
"src/EstateSale/EstateSaleWithFee.sol": "EstateSaleWithFee"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 2000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"landAddress","type":"address"},{"internalType":"address","name":"sandContractAddress","type":"address"},{"internalType":"address","name":"initialMetaTx","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address payable","name":"initialWalletAddress","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"expiryTime","type":"uint256"},{"internalType":"address","name":"initialSigningWallet","type":"address"},{"internalType":"uint256","name":"initialMaxCommissionRate","type":"uint256"},{"internalType":"address","name":"estate","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"feeDistributor","type":"address"}],"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":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"topCornerId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountPaid","type":"uint256"}],"name":"LandQuadPurchased","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commission","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commissionRate","type":"uint256"}],"name":"ReferralUsed","type":"event"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"reserved","type":"address"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"priceInSand","type":"uint256"},{"internalType":"uint256","name":"adjustedPriceInSand","type":"uint256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"buyLandWithSand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"decodeReferral","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExpiryTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxCommisionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSandMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigningWallet","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":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"referee","type":"address"},{"internalType":"uint256","name":"expiryTime","type":"uint256"},{"internalType":"uint256","name":"commissionRate","type":"uint256"}],"name":"isReferralValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMultiplier","type":"uint256"}],"name":"rebalanceSand","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"},{"inputs":[{"internalType":"address payable","name":"newWallet","type":"address"}],"name":"setReceivingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxCommissionRate","type":"uint256"}],"name":"updateMaxCommissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigningWallet","type":"address"}],"name":"updateSigningWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"withdrawAssets","outputs":[],"stateMutability":"nonpayable","type":"function"}]