文件 1 的 10: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");
_;
}
}
文件 2 的 10: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);
}
文件 3 的 10: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);
}
文件 4 的 10:EstateSale.sol
pragma solidity 0.6.5;
import "../contracts_common/src/Libraries/SafeMathWithRequire.sol";
import "./LandToken.sol";
import "../contracts_common/src/Interfaces/ERC1155.sol";
import "../contracts_common/src/Interfaces/ERC20.sol";
import "../contracts_common/src/BaseWithStorage/MetaTransactionReceiver.sol";
import "../contracts_common/src/Interfaces/Medianizer.sol";
import "../ReferralValidator/ReferralValidator.sol";
contract EstateSale is MetaTransactionReceiver, ReferralValidator {
using SafeMathWithRequire for uint256;
uint256 internal constant GRID_SIZE = 408;
uint256 internal constant daiPrice = 14400000000000000;
ERC1155 internal immutable _asset;
LandToken internal immutable _land;
ERC20 internal immutable _sand;
Medianizer private immutable _medianizer;
ERC20 private immutable _dai;
address internal immutable _estate;
address payable internal _wallet;
uint256 internal immutable _expiryTime;
bytes32 internal immutable _merkleRoot;
bool _sandEnabled = false;
bool _etherEnabled = true;
bool _daiEnabled = false;
event LandQuadPurchased(
address indexed buyer,
address indexed to,
uint256 indexed topCornerId,
uint256 size,
uint256 price,
address token,
uint256 amountPaid
);
constructor(
address landAddress,
address sandContractAddress,
address initialMetaTx,
address admin,
address payable initialWalletAddress,
bytes32 merkleRoot,
uint256 expiryTime,
address medianizerContractAddress,
address daiTokenContractAddress,
address initialSigningWallet,
uint256 initialMaxCommissionRate,
address estate,
address asset
) public ReferralValidator(initialSigningWallet, initialMaxCommissionRate) {
_land = LandToken(landAddress);
_sand = ERC20(sandContractAddress);
_setMetaTransactionProcessor(initialMetaTx, true);
_wallet = initialWalletAddress;
_merkleRoot = merkleRoot;
_expiryTime = expiryTime;
_medianizer = Medianizer(medianizerContractAddress);
_dai = ERC20(daiTokenContractAddress);
_admin = admin;
_estate = estate;
_asset = ERC1155(asset);
}
function setReceivingWallet(address payable newWallet) external {
require(newWallet != address(0), "receiving wallet cannot be zero address");
require(msg.sender == _admin, "only admin can change the receiving wallet");
_wallet = newWallet;
}
function setDAIEnabled(bool enabled) external {
require(msg.sender == _admin, "only admin can enable/disable DAI");
_daiEnabled = enabled;
}
function isDAIEnabled() external view returns (bool) {
return _daiEnabled;
}
function setETHEnabled(bool enabled) external {
require(msg.sender == _admin, "only admin can enable/disable ETH");
_etherEnabled = enabled;
}
function isETHEnabled() external view returns (bool) {
return _etherEnabled;
}
function setSANDEnabled(bool enabled) external {
require(msg.sender == _admin, "only admin can enable/disable SAND");
_sandEnabled = enabled;
}
function isSANDEnabled() external view returns (bool) {
return _sandEnabled;
}
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, "cannot buy reserved Land");
bytes32 leaf = _generateLandHash(x, y, size, price, reserved, salt, assetIds);
require(_verify(proof, leaf), "Invalid land provided");
}
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 buyLandWithSand(
address buyer,
address to,
address reserved,
uint256 x,
uint256 y,
uint256 size,
uint256 priceInSand,
bytes32 salt,
uint256[] calldata assetIds,
bytes32[] calldata proof,
bytes calldata referral
) external {
require(_sandEnabled, "sand payments not enabled");
_checkValidity(buyer, reserved, x, y, size, priceInSand, salt, assetIds, proof);
handleReferralWithERC20(buyer, priceInSand, referral, _wallet, address(_sand));
_mint(buyer, to, x, y, size, priceInSand, address(_sand), priceInSand);
_sendAssets(to, assetIds);
}
function buyLandWithETH(
address buyer,
address to,
address reserved,
uint256 x,
uint256 y,
uint256 size,
uint256 priceInSand,
bytes32 salt,
uint256[] calldata assetIds,
bytes32[] calldata proof,
bytes calldata referral
) external payable {
require(_etherEnabled, "ether payments not enabled");
_checkValidity(buyer, reserved, x, y, size, priceInSand, salt, assetIds, proof);
uint256 ETHRequired = getEtherAmountWithSAND(priceInSand);
require(msg.value >= ETHRequired, "not enough ether sent");
if (msg.value - ETHRequired > 0) {
msg.sender.transfer(msg.value - ETHRequired);
}
handleReferralWithETH(ETHRequired, referral, _wallet);
_mint(buyer, to, x, y, size, priceInSand, address(0), ETHRequired);
_sendAssets(to, assetIds);
}
function buyLandWithDAI(
address buyer,
address to,
address reserved,
uint256 x,
uint256 y,
uint256 size,
uint256 priceInSand,
bytes32 salt,
uint256[] calldata assetIds,
bytes32[] calldata proof,
bytes calldata referral
) external {
require(_daiEnabled, "dai payments not enabled");
_checkValidity(buyer, reserved, x, y, size, priceInSand, salt, assetIds, proof);
uint256 DAIRequired = priceInSand.mul(daiPrice).div(1000000000000000000);
handleReferralWithERC20(buyer, DAIRequired, referral, _wallet, address(_dai));
_mint(buyer, to, x, y, size, priceInSand, address(_dai), DAIRequired);
_sendAssets(to, assetIds);
}
function getExpiryTime() external view returns (uint256) {
return _expiryTime;
}
function merkleRoot() external view returns (bytes32) {
return _merkleRoot;
}
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 _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 getEtherAmountWithSAND(uint256 sandAmount) public view returns (uint256) {
uint256 ethUsdPair = getEthUsdPair();
return sandAmount.mul(daiPrice).div(ethUsdPair);
}
function getEthUsdPair() internal view returns (uint256) {
bytes32 pair = _medianizer.read();
return uint256(pair);
}
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 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, "");
}
}
文件 5 的 10:LandToken.sol
pragma solidity 0.6.5;
interface LandToken {
function mintQuad(
address to,
uint256 size,
uint256 x,
uint256 y,
bytes calldata data
) external;
}
文件 6 的 10:Medianizer.sol
pragma solidity ^0.6.0;
interface Medianizer {
function read() external view returns (bytes32);
}
文件 7 的 10: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];
}
}
文件 8 的 10:ReferralValidator.sol
pragma solidity 0.6.5;
import "../contracts_common/src/Libraries/SigUtil.sol";
import "../contracts_common/src/Libraries/SafeMathWithRequire.sol";
import "../contracts_common/src/Interfaces/ERC20.sol";
import "../contracts_common/src/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);
}
}
文件 9 的 10: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;
}
}
文件 10 的 10: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);
}
}
{
"compilationTarget": {
"src/EstateSale/EstateSale.sol": "EstateSale"
},
"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":"medianizerContractAddress","type":"address"},{"internalType":"address","name":"daiTokenContractAddress","type":"address"},{"internalType":"address","name":"initialSigningWallet","type":"address"},{"internalType":"uint256","name":"initialMaxCommissionRate","type":"uint256"},{"internalType":"address","name":"estate","type":"address"},{"internalType":"address","name":"asset","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":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"buyLandWithDAI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"buyLandWithETH","outputs":[],"stateMutability":"payable","type":"function"},{"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":"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":[{"internalType":"uint256","name":"sandAmount","type":"uint256"}],"name":"getEtherAmountWithSAND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"getSigningWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDAIEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isETHEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"isSANDEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"bool","name":"enabled","type":"bool"}],"name":"setDAIEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setETHEnabled","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":"bool","name":"enabled","type":"bool"}],"name":"setSANDEnabled","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"}]