编译器
0.8.24+commit.e11b9ed9
文件 1 的 34:Arrays.sol
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";
library Arrays {
using StorageSlot for bytes32;
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getAddressSlot();
}
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getBytes32Slot();
}
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getUint256Slot();
}
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
}
文件 2 的 34:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 3 的 34:ECDSA.sol
pragma solidity ^0.8.20;
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
error ECDSAInvalidSignature();
error ECDSAInvalidSignatureLength(uint256 length);
error ECDSAInvalidSignatureS(bytes32 s);
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
文件 4 的 34:ERC1155.sol
pragma solidity ^0.8.20;
import {IERC1155} from "./IERC1155.sol";
import {IERC1155Receiver} from "./IERC1155Receiver.sol";
import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol";
import {Context} from "../../utils/Context.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {Arrays} from "../../utils/Arrays.sol";
import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol";
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
using Arrays for uint256[];
using Arrays for address[];
mapping(uint256 id => mapping(address account => uint256)) private _balances;
mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
string private _uri;
constructor(string memory uri_) {
_setURI(uri_);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
function uri(uint256 ) public view virtual returns (string memory) {
return _uri;
}
function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
return _balances[id][account];
}
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view virtual returns (uint256[] memory) {
if (accounts.length != ids.length) {
revert ERC1155InvalidArrayLength(ids.length, accounts.length);
}
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
}
return batchBalances;
}
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeTransferFrom(from, to, id, value, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeBatchTransferFrom(from, to, ids, values, data);
}
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
if (ids.length != values.length) {
revert ERC1155InvalidArrayLength(ids.length, values.length);
}
address operator = _msgSender();
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids.unsafeMemoryAccess(i);
uint256 value = values.unsafeMemoryAccess(i);
if (from != address(0)) {
uint256 fromBalance = _balances[id][from];
if (fromBalance < value) {
revert ERC1155InsufficientBalance(from, fromBalance, value, id);
}
unchecked {
_balances[id][from] = fromBalance - value;
}
}
if (to != address(0)) {
_balances[id][to] += value;
}
}
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
emit TransferSingle(operator, from, to, id, value);
} else {
emit TransferBatch(operator, from, to, ids, values);
}
}
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal virtual {
_update(from, to, ids, values);
if (to != address(0)) {
address operator = _msgSender();
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
_doSafeTransferAcceptanceCheck(operator, from, to, id, value, data);
} else {
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data);
}
}
}
function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
function _burn(address from, uint256 id, uint256 value) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC1155InvalidOperator(address(0));
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 value,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC1155InvalidReceiver(to);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC1155InvalidReceiver(to);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
function _asSingletonArrays(
uint256 element1,
uint256 element2
) private pure returns (uint256[] memory array1, uint256[] memory array2) {
assembly {
array1 := mload(0x40)
mstore(array1, 1)
mstore(add(array1, 0x20), element1)
array2 := add(array1, 0x40)
mstore(array2, 1)
mstore(add(array2, 0x20), element2)
mstore(0x40, add(array2, 0x40))
}
}
}
文件 5 的 34:ERC1155Burnable.sol
pragma solidity ^0.8.20;
import {ERC1155} from "../ERC1155.sol";
abstract contract ERC1155Burnable is ERC1155 {
function burn(address account, uint256 id, uint256 value) public virtual {
if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) {
revert ERC1155MissingApprovalForAll(_msgSender(), account);
}
_burn(account, id, value);
}
function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual {
if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) {
revert ERC1155MissingApprovalForAll(_msgSender(), account);
}
_burnBatch(account, ids, values);
}
}
文件 6 的 34:ERC1155Supply.sol
pragma solidity ^0.8.20;
import {ERC1155} from "../ERC1155.sol";
abstract contract ERC1155Supply is ERC1155 {
mapping(uint256 id => uint256) private _totalSupply;
uint256 private _totalSupplyAll;
function totalSupply(uint256 id) public view virtual returns (uint256) {
return _totalSupply[id];
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupplyAll;
}
function exists(uint256 id) public view virtual returns (bool) {
return totalSupply(id) > 0;
}
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal virtual override {
super._update(from, to, ids, values);
if (from == address(0)) {
uint256 totalMintValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
_totalSupply[ids[i]] += value;
totalMintValue += value;
}
_totalSupplyAll += totalMintValue;
}
if (to == address(0)) {
uint256 totalBurnValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
unchecked {
_totalSupply[ids[i]] -= value;
totalBurnValue += value;
}
}
unchecked {
_totalSupplyAll -= totalBurnValue;
}
}
}
}
文件 7 的 34:ERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 34:ERC721.sol
pragma solidity ^0.8.20;
import {IERC721} from "./IERC721.sol";
import {IERC721Receiver} from "./IERC721Receiver.sol";
import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {Strings} from "../../utils/Strings.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol";
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
if (from != address(0)) {
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
_checkOnERC721Received(address(0), to, tokenId, data);
}
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
function _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC721InvalidReceiver(to);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
文件 9 的 34:ERC721Burnable.sol
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {Context} from "../../../utils/Context.sol";
abstract contract ERC721Burnable is Context, ERC721 {
function burn(uint256 tokenId) public virtual {
_update(address(0), tokenId, _msgSender());
}
}
文件 10 的 34:ERC721Enumerable.sol
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {IERC721Enumerable} from "./IERC721Enumerable.sol";
import {IERC165} from "../../../utils/introspection/ERC165.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
error ERC721OutOfBoundsIndex(address owner, uint256 index);
error ERC721EnumerableForbiddenBatchMint();
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId;
_ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId;
_allTokensIndex[lastTokenId] = tokenIndex;
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
文件 11 的 34:IERC1155.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
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 account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
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;
}
文件 12 的 34:IERC1155MetadataURI.sol
pragma solidity ^0.8.20;
import {IERC1155} from "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 13 的 34:IERC1155Receiver.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
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);
}
文件 14 的 34:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 15 的 34:IERC721.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
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);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 16 的 34:IERC721Enumerable.sol
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 17 的 34:IERC721Metadata.sol
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 18 的 34:IERC721Receiver.sol
pragma solidity ^0.8.20;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 19 的 34:LibPRNG_01.sol
pragma solidity ^0.8.4;
library LibPRNG_01 {
error InvalidInitialLazyShufflerLength();
error InvalidNewLazyShufflerLength();
error LazyShufflerNotInitialized();
error LazyShufflerAlreadyInitialized();
error LazyShuffleFinished();
error LazyShufflerGetOutOfBounds();
uint256 internal constant WAD = 1e18;
struct PRNG {
uint256 state;
}
struct LazyShuffler {
uint256 _state;
}
function seed(PRNG memory prng, uint256 state) internal pure {
assembly {
mstore(prng, state)
}
}
function next(PRNG memory prng) internal pure returns (uint256 result) {
assembly {
result := keccak256(prng, 0x20)
mstore(prng, result)
}
}
function uniform(
PRNG memory prng,
uint256 upper
) internal pure returns (uint256 result) {
assembly {
for {
} 1 {
} {
result := keccak256(prng, 0x20)
mstore(prng, result)
if iszero(lt(result, mod(sub(0, upper), upper))) {
break
}
}
result := mod(result, upper)
}
}
function shuffle(PRNG memory prng, uint256[] memory a) internal pure {
assembly {
let n := mload(a)
let w := not(0)
let mask := shr(128, w)
if n {
for {
a := add(a, 0x20)
} 1 {
} {
let r := keccak256(prng, 0x20)
mstore(prng, r)
{
let j := add(a, shl(5, mod(shr(128, r), n)))
n := add(n, w)
if iszero(n) {
break
}
let i := add(a, shl(5, n))
let t := mload(i)
mstore(i, mload(j))
mstore(j, t)
}
{
let j := add(a, shl(5, mod(and(r, mask), n)))
n := add(n, w)
if iszero(n) {
break
}
let i := add(a, shl(5, n))
let t := mload(i)
mstore(i, mload(j))
mstore(j, t)
}
}
}
}
}
function shuffle(PRNG memory prng, bytes memory a) internal pure {
assembly {
let n := mload(a)
let w := not(0)
let mask := shr(128, w)
if n {
let b := add(a, 0x01)
for {
a := add(a, 0x20)
} 1 {
} {
let r := keccak256(prng, 0x20)
mstore(prng, r)
{
let o := mod(shr(128, r), n)
n := add(n, w)
if iszero(n) {
break
}
let t := mload(add(b, n))
mstore8(add(a, n), mload(add(b, o)))
mstore8(add(a, o), t)
}
{
let o := mod(and(r, mask), n)
n := add(n, w)
if iszero(n) {
break
}
let t := mload(add(b, n))
mstore8(add(a, n), mload(add(b, o)))
mstore8(add(a, o), t)
}
}
}
}
}
function standardNormalWad(
PRNG memory prng
) internal pure returns (int256 result) {
assembly {
result := keccak256(prng, 0x20)
mstore(prng, result)
let
n
:= 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43
let a := 0x100000000000000000000000000000051
let
m
:= 0x1fffffffffffffff1fffffffffffffff1fffffffffffffff1fffffffffffffff
let s := 0x1000000000000000100000000000000010000000000000001
let r1 := mulmod(result, a, n)
let r2 := mulmod(r1, a, n)
let r3 := mulmod(r2, a, n)
result := sub(
sar(
96,
mul(
26614938895861601847173011183,
add(
add(
shr(
192,
mul(s, add(and(m, result), and(m, r1)))
),
shr(192, mul(s, add(and(m, r2), and(m, r3))))
),
shr(192, mul(s, and(m, mulmod(r3, a, n))))
)
)
),
7745966692414833770
)
}
}
function exponentialWad(
PRNG memory prng
) internal pure returns (uint256 result) {
assembly {
let r := keccak256(prng, 0x20)
mstore(prng, r)
let p := shl(129, r)
let w := shl(1, r)
if iszero(gt(w, p)) {
let
n
:= 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43
let a := 0x100000000000000000000000000000051
for {
} 1 {
} {
r := mulmod(r, a, n)
if iszero(lt(shl(129, r), w)) {
r := mulmod(r, a, n)
result := add(1000000000000000000, result)
w := shl(1, r)
p := shl(129, r)
if iszero(lt(w, p)) {
break
}
continue
}
w := shl(1, r)
if iszero(lt(w, shl(129, r))) {
break
}
}
}
result := add(div(p, shl(129, 170141183460469231732)), result)
}
}
function initialize(LazyShuffler storage $, uint256 n) internal {
assembly {
if iszero(lt(sub(n, 1), 0xfffffffe)) {
mstore(0x00, 0x83b53941)
revert(0x1c, 0x04)
}
if sload($.slot) {
mstore(0x00, 0x0c9f11f2)
revert(0x1c, 0x04)
}
mstore(0x00, $.slot)
sstore(
$.slot,
or(shl(224, n), shl(32, shr(64, keccak256(0x00, 0x20))))
)
}
}
function grow(LazyShuffler storage $, uint256 n) internal {
assembly {
let state := sload($.slot)
if lt(n, shr(224, state)) {
mstore(0x00, 0xbed37c6e)
revert(0x1c, 0x04)
}
if iszero(state) {
mstore(0x00, 0x1ead2566)
revert(0x1c, 0x04)
}
sstore($.slot, or(shl(224, n), shr(32, shl(32, state))))
}
}
function restart(LazyShuffler storage $) internal {
assembly {
let state := sload($.slot)
if iszero(state) {
mstore(0x00, 0x1ead2566)
revert(0x1c, 0x04)
}
sstore($.slot, shl(32, shr(32, state)))
}
}
function numShuffled(
LazyShuffler storage $
) internal view returns (uint256 result) {
assembly {
result := and(0xffffffff, sload($.slot))
}
}
function length(
LazyShuffler storage $
) internal view returns (uint256 result) {
assembly {
result := shr(224, sload($.slot))
}
}
function initialized(
LazyShuffler storage $
) internal view returns (bool result) {
assembly {
result := iszero(iszero(sload($.slot)))
}
}
function finished(
LazyShuffler storage $
) internal view returns (bool result) {
assembly {
let state := sload($.slot)
if iszero(state) {
mstore(0x00, 0x1ead2566)
revert(0x1c, 0x04)
}
result := eq(shr(224, state), and(0xffffffff, state))
}
}
function get(
LazyShuffler storage $,
uint256 index
) internal view returns (uint256 result) {
assembly {
let state := sload($.slot)
let n := shr(224, state)
if iszero(lt(index, n)) {
mstore(0x00, 0x61367cc4)
revert(0x1c, 0x04)
}
let u32 := gt(n, 0xfffe)
let s := add(shr(sub(4, u32), index), shr(64, shl(32, state)))
let o := shl(add(4, u32), and(index, shr(u32, 15)))
let m := sub(shl(shl(u32, 16), 1), 1)
result := and(m, shr(o, sload(s)))
result := xor(
index,
mul(xor(index, sub(result, 1)), iszero(iszero(result)))
)
}
}
function next(
LazyShuffler storage $,
uint256 randomness
) internal returns (uint256 chosen) {
assembly {
function _get(u32_, state_, i_) -> _value {
let s_ := add(shr(sub(4, u32_), i_), shr(64, shl(32, state_)))
let o_ := shl(add(4, u32_), and(i_, shr(u32_, 15)))
let m_ := sub(shl(shl(u32_, 16), 1), 1)
_value := and(m_, shr(o_, sload(s_)))
_value := xor(
i_,
mul(xor(i_, sub(_value, 1)), iszero(iszero(_value)))
)
}
function _set(u32_, state_, i_, value_) {
let s_ := add(shr(sub(4, u32_), i_), shr(64, shl(32, state_)))
let o_ := shl(add(4, u32_), and(i_, shr(u32_, 15)))
let m_ := sub(shl(shl(u32_, 16), 1), 1)
let v_ := sload(s_)
value_ := mul(iszero(eq(i_, value_)), add(value_, 1))
sstore(s_, xor(v_, shl(o_, and(m_, xor(shr(o_, v_), value_)))))
}
let state := sload($.slot)
let shuffled := and(0xffffffff, state)
let n := shr(224, state)
let remainder := sub(n, shuffled)
if iszero(remainder) {
mstore(0x00, 0x51065f79)
revert(0x1c, 0x04)
}
mstore(0x00, randomness)
mstore(0x20, shuffled)
let index := add(mod(keccak256(0x00, 0x40), remainder), shuffled)
chosen := _get(gt(n, 0xfffe), state, index)
_set(
gt(n, 0xfffe),
state,
index,
_get(gt(n, 0xfffe), state, shuffled)
)
_set(gt(n, 0xfffe), state, shuffled, chosen)
sstore($.slot, add(1, state))
}
}
}
文件 20 的 34:LiberoERC1155_01.sol
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
contract LiberoERC1155_01 is ERC1155, ERC1155Burnable, Ownable, ERC1155Supply {
string public name;
string public symbol;
constructor(
string memory uri,
string memory _name,
string memory _symbol,
address initialOwner
)
ERC1155(string(abi.encodePacked(uri, "{id}.json")))
Ownable(initialOwner)
{
name = _name;
symbol = _symbol;
}
function mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
) public onlyOwner {
_mint(account, id, amount, data);
}
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public onlyOwner {
_mintBatch(to, ids, amounts, data);
}
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal override(ERC1155, ERC1155Supply) {
super._update(from, to, ids, values);
}
}
文件 21 的 34:LiberoERC721_01.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract LiberoERC721_01 is ERC721, ERC721Enumerable, ERC721Burnable, Ownable {
string private _uri;
constructor(
string memory uri,
string memory name,
string memory symbol,
address initialOwner
) ERC721(name, symbol) Ownable(initialOwner) {
_uri = uri;
}
function tokenURI(
uint256 tokenId
) public view override(ERC721) returns (string memory) {
return
string(abi.encodePacked(_uri, Strings.toString(tokenId), ".json"));
}
function _update(
address to,
uint256 tokenId,
address auth
) internal override(ERC721, ERC721Enumerable) returns (address) {
return super._update(to, tokenId, auth);
}
function _increaseBalance(
address account,
uint128 value
) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function supportsInterface(
bytes4 interfaceId
) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function mintTo(address to, uint256 tokenId) public {
_safeMint(to, tokenId);
}
}
文件 22 的 34:LiberoMintFactory_01.sol
pragma solidity ^0.8.24;
import "./LiberoERC721_01.sol";
import "./LiberoERC1155_01.sol";
contract LiberoMintFactory_01 {
function deployLiberoERC721(
string memory mintUri,
string memory mintName,
string memory mintSymbol,
address initialOwner
) public returns (LiberoERC721_01 contractAddress) {
LiberoERC721_01 erc721 = new LiberoERC721_01(
mintUri,
mintName,
mintSymbol,
initialOwner
);
return erc721;
}
function deployLiberoERC1155(
string memory mintUri,
string memory mintName,
string memory mintSymbol,
address initialOwner
) public returns (LiberoERC1155_01 contractAddress) {
LiberoERC1155_01 erc1155 = new LiberoERC1155_01(
mintUri,
mintName,
mintSymbol,
initialOwner
);
return erc1155;
}
}
文件 23 的 34:LiberoRaffle_01.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./LiberoERC721_01.sol";
import "./LiberoERC1155_01.sol";
import "./LiberoMintFactory_01.sol";
import "./LiberoReward_01.sol";
import "./LibPRNG_01.sol";
import "./Ticketing_01.sol";
import "./TicketingFactory_01.sol";
contract SoladyPRNG {
LibPRNG_01.PRNG private state;
constructor(uint256 _state) {
state = LibPRNG_01.PRNG(_state);
}
function random(uint256 _upperBound) public view returns (uint256) {
return LibPRNG_01.uniform(state, _upperBound);
}
}
contract LiberoRaffle_01 is Ownable {
event ERC721Deployed(address contractAddress);
event ERC1155Deployed(address contractAddress);
LiberoRewards_01.Raffle[] private _raffleInfo;
LiberoRewards_01.RaffleExt[] private _raffleExt;
uint32 private _raffleNr;
address private _manager;
LiberoMintFactory_01 private _liberoMintFactory;
TicketingFactory_01 private _ticketingFactory;
constructor(
address manager,
address liberoMintFactory,
address ticketingFactory
) Ownable(msg.sender) {
_liberoMintFactory = LiberoMintFactory_01(liberoMintFactory);
_ticketingFactory = TicketingFactory_01(ticketingFactory);
_manager = manager;
}
modifier onlyManager() {
require(_manager == msg.sender, "CALLER_NOT_MANAGER");
_;
}
function setManager(address manager) public onlyOwner {
_manager = manager;
}
function newRaffle(
uint32 id,
uint256 payAmount,
address organizer,
uint32 totalTickets,
uint32 totalPriorityTickets,
uint32 maxTicketsPerWallet,
uint32 maxRewardsPerWallet,
uint32 availableRewards,
uint8 rewardIf,
address rewardContract,
string memory mintUri,
string memory mintName,
string memory mintSymbol,
bool shouldDistributeRewards,
bool shouldRefundNonWinning,
uint256 startAt,
uint256 endAt,
uint256 raffleAt,
uint256 sysTicketPrice,
uint16 ownerFeePct,
uint16 ownerTipPct,
LiberoRewards_01.Requirement[] memory requirements,
bytes memory signature
) public payable {
address recoveredSigner = LiberoRewards_01
.ext_newRaffleValidateAndCheckSignature(
id,
payAmount,
organizer,
totalTickets,
totalPriorityTickets,
maxTicketsPerWallet,
maxRewardsPerWallet,
availableRewards,
rewardIf,
rewardContract,
mintUri,
mintName,
mintSymbol,
shouldDistributeRewards,
shouldRefundNonWinning,
startAt,
endAt,
raffleAt,
sysTicketPrice,
ownerFeePct,
ownerTipPct,
requirements,
signature
);
require(recoveredSigner == _manager, "RAFFLE_NEEDS_VALID_SIGNATURE");
_raffleInfo.push();
_raffleExt.push();
_raffleNr = uint16(_raffleInfo.length) - 1;
LiberoRewards_01.Raffle storage _newRaffle = _raffleInfo[_raffleNr];
_newRaffle.availableRewards = availableRewards;
_newRaffle.rewardIf = rewardIf;
_newRaffle.organizer = organizer;
_newRaffle.rewardContract = rewardContract;
_newRaffle.availableRewards = availableRewards;
_newRaffle.shouldDistributeRewards = shouldDistributeRewards;
_newRaffle.shouldRefundNonWinning = shouldRefundNonWinning;
_newRaffle.startAt = startAt;
_newRaffle.endAt = endAt;
_newRaffle.raffleAt = raffleAt;
_newRaffle.sysTicketPrice = sysTicketPrice;
if (rewardContract == address(0)) {
require(
shouldDistributeRewards && rewardIf != IF_NONE,
"MINT_REQUIRES_DISTRIBUTION_OF_REWARDS"
);
require(bytes(mintSymbol).length > 0, "MINT_REQUIRESTOKEN_SYMBOL");
require(bytes(mintName).length > 0, "MINT_REQUIRESTOKEN_NAME");
if (rewardIf == IF_ERC721) {
LiberoERC721_01 mintable = _liberoMintFactory
.deployLiberoERC721(
mintUri,
mintName,
mintSymbol,
address(this)
);
emit ERC721Deployed(address(mintable));
_newRaffle.mintContract = address(mintable);
} else if (rewardIf == IF_ERC1155) {
LiberoERC1155_01 mintable = _liberoMintFactory
.deployLiberoERC1155(
mintUri,
mintName,
mintSymbol,
address(this)
);
emit ERC1155Deployed(address(mintable));
_newRaffle.mintContract = address(mintable);
}
}
_newRaffle.requirements = requirements;
_newRaffle.tickets = _ticketingFactory.deployTicketing(
address(this),
totalTickets,
totalPriorityTickets,
maxTicketsPerWallet
);
_newRaffle.maxRewardsPerWallet = maxRewardsPerWallet;
payable(owner()).transfer(payAmount);
emit LiberoRewards_01.RaffleCreated(_raffleNr, id);
}
function addRewards(
uint32 raffleNr,
uint256 from,
LiberoRewards_01.Reward[] memory rewards
) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(activeRaffle.rewards.length == from, "ADD_REWARDS_FROM_ERROR");
require(
rewards.length + activeRaffle.rewards.length <=
activeRaffle.availableRewards,
"ADD_REWARDS_TOO_MANY"
);
if (
activeRaffle.shouldDistributeRewards &&
activeRaffle.rewardContract != address(0)
) {
LiberoRewards_01.ext_approveAwardInternal(
activeRaffle.rewardIf,
activeRaffle.rewardContract,
activeRaffle.organizer,
rewards
);
}
for (uint256 i = 0; i < rewards.length; i++) {
activeRaffle.rewards.push(rewards[i]);
}
activeRaffle.totalRewards = activeRaffle.rewards.length;
}
function getRaffleInfo(
uint32 raffleNr
) public view onlyManager returns (LiberoRewards_01.Raffle memory) {
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
delete activeRaffle.rewards;
delete activeRaffle.tickets;
delete activeRaffle.winningTickets;
return activeRaffle;
}
function getRaffleInfoCnt(
uint32 raffleNr
)
public
view
onlyManager
returns (
uint256 rewardsLen,
uint256 ticketsLen,
uint256 ticketsValidPriorityLen,
uint256 ticketsValidLen,
uint256 winningTicketsLen,
bool validated
)
{
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
rewardsLen = activeRaffle.rewards.length;
ticketsLen = activeRaffle.tickets.getAllTicketsLength();
ticketsValidPriorityLen = activeRaffle.tickets.getValidTicketsLength(
true
);
ticketsValidLen = activeRaffle.tickets.getValidTicketsLength(false);
winningTicketsLen = activeRaffle.winningTickets.length;
validated = activeRaffle.tickets.getTicketsValidated();
}
function getRaffleInfoRewards(
uint32 raffleNr,
uint256 fromIx,
uint256 toIx
) public view onlyManager returns (LiberoRewards_01.Reward[] memory) {
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
LiberoRewards_01.Reward[] memory res = new LiberoRewards_01.Reward[](
toIx - fromIx
);
for (uint256 i = fromIx; i < toIx; i++) {
res[i - fromIx] = activeRaffle.rewards[i];
}
return res;
}
function getRaffleInfoTickets(
uint32 raffleNr,
uint256 fromIx,
uint256 toIx
) public view onlyManager returns (Ticketing_01.Ticket[] memory) {
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
Ticketing_01.Ticket[] memory res = new Ticketing_01.Ticket[](
toIx - fromIx
);
for (uint256 i = fromIx; i < toIx; i++) {
res[i - fromIx] = activeRaffle.tickets.getTicketAt(i);
}
return res;
}
function getRaffleInfoValidTickets(
uint32 raffleNr,
bool isPriority,
uint256 fromIx,
uint256 toIx
) public view onlyManager returns (Ticketing_01.Ticket[] memory) {
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
Ticketing_01.Ticket[] memory res = new Ticketing_01.Ticket[](
toIx - fromIx
);
for (uint256 i = fromIx; i < toIx; i++) {
res[i - fromIx] = activeRaffle.tickets.getValidTicketAtIx(
isPriority,
i
);
}
return res;
}
function getRaffleInfoWinningTickets(
uint32 raffleNr,
uint256 fromIx,
uint256 toIx
)
public
view
onlyManager
returns (LiberoRewards_01.WinningTicket[] memory)
{
LiberoRewards_01.Raffle memory activeRaffle = _raffleInfo[raffleNr];
LiberoRewards_01.WinningTicket[]
memory res = new LiberoRewards_01.WinningTicket[](toIx - fromIx);
for (uint256 i = fromIx; i < toIx; i++) {
res[i - fromIx] = activeRaffle.winningTickets[i];
}
return res;
}
function getRaffleInfoRewardsPerWallet(
uint32 raffleNr,
address wallet
) public view onlyManager returns (uint32) {
LiberoRewards_01.RaffleExt storage activeRaffleExt = _raffleExt[
raffleNr
];
return activeRaffleExt.rewardsPerWallet[wallet];
}
function getRaffleInfoWinningTicketKeys(
uint32 raffleNr,
Ticketing_01.Ticket memory ticket
) public view onlyManager returns (bool) {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
LiberoRewards_01.RaffleExt storage activeRaffleExt = _raffleExt[
raffleNr
];
uint256 ticketKey = activeRaffle.tickets.getTicketKeyExt(ticket);
return activeRaffleExt.winningTicketKeys[ticketKey];
}
function getRaffleInfoTicketKeyExt(
uint32 raffleNr,
Ticketing_01.Ticket memory ticket
) public view onlyManager returns (uint256) {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
return activeRaffle.tickets.getTicketKeyExt(ticket);
}
function getRaffleInfoTicketValidationInfo(
uint32 raffleNr
)
public
view
returns (
uint256 _validatedUntil,
bool _validated,
uint256 _totalTickets,
uint256 _totalPriorityTickets,
uint256 _maxTicketsPerWallet,
uint256 _totalTicketsSold,
uint256 _returnedTickets
)
{
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
return activeRaffle.tickets.getTicketValidationInfo();
}
function buyTickets(
uint32 raffleNr,
Ticketing_01.Ticket[] calldata toBuy,
Ticketing_01.Ticket[] calldata toReturn,
uint256 tip,
bytes memory signature
) public payable {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
(
address recoveredSigner,
uint256 netPayAmount,
uint256 netRefundAmount
) = LiberoRewards_01.ext_buyTicketsValidateAndCheckSignature(
raffleNr,
activeRaffle,
toBuy,
toReturn,
tip,
signature
);
require(
recoveredSigner == _manager,
"BUY_TICKET_NEEDS_VALID_SIGNATURE"
);
if (toBuy.length > 0) activeRaffle.tickets.buyTickets(raffleNr, toBuy);
if (toReturn.length > 0)
activeRaffle.tickets.returnTickets(raffleNr, toReturn);
payable(owner()).transfer(toBuy.length * activeRaffle.sysTicketPrice);
if (netPayAmount > 0) {
activeRaffle.fees += netPayAmount;
} else {
activeRaffle.fees -= netRefundAmount;
payable(msg.sender).transfer(netRefundAmount);
}
activeRaffle.tips += tip;
if (tip > 0 || netPayAmount > 0) {
emit LiberoRewards_01.Payment(
raffleNr,
msg.sender,
tip,
netPayAmount,
netRefundAmount > 0
);
}
}
function seedRaffle(uint32 raffleNr, uint256 seed) public {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(
activeRaffle.availableRewards == activeRaffle.rewards.length,
"REWARDS_NOT_ADDED"
);
require(
(msg.sender == activeRaffle.organizer &&
block.timestamp >= activeRaffle.raffleAt) ||
(msg.sender == _manager &&
block.timestamp >= (activeRaffle.raffleAt + 1 hours)),
"SEED_RAFFLE_NOT_AUTHORIZED"
);
require(!activeRaffle.prngInitialized, "PRNG_ALREADY_INITIALIZED");
activeRaffle.prngState = uint256(
keccak256(
abi.encodePacked(
block.prevrandao,
block.timestamp,
msg.sender,
seed,
raffleNr
)
)
);
activeRaffle.prngInitialized = true;
}
function validateTickets(uint32 raffleNr, uint256 cnt) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(activeRaffle.prngInitialized, "RAFFLE_PRNG_NOT_INITIALIZED");
activeRaffle.tickets.validateTickets(cnt);
if (activeRaffle.tickets.getTicketsValidated()) {
activeRaffle.totalTickets =
activeRaffle.tickets.getValidTicketsLength(true) +
activeRaffle.tickets.getValidTicketsLength(false);
if (activeRaffle.totalRewards > activeRaffle.totalTickets) {
activeRaffle.totalRewards = activeRaffle.totalTickets;
}
}
}
function raffle(
uint32 raffleNr,
bool isPriority,
uint256 cnt
) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(activeRaffle.prngInitialized, "RAFFLE_PRNG_NOT_INITIALIZED");
require(
activeRaffle.tickets.getTicketsValidated(),
"TICKETS_NOT_VALIDATED"
);
uint256 priorityTicketsLength = activeRaffle
.tickets
.getValidTicketsLength(true);
require(
activeRaffle.nextRewardIx < activeRaffle.totalRewards,
"RAFFLE_FINISHED"
);
if (isPriority) {
require(
activeRaffle.pickedRewards < priorityTicketsLength,
"RAFFLE_FINISHED_PRIORITY"
);
} else {
require(
activeRaffle.pickedRewards >= priorityTicketsLength,
"RAFFLE_NOT_FINISHED_PRIORITY"
);
require(
activeRaffle.nextRewardIx < activeRaffle.totalTickets,
"RAFFLE_FINISHED_OTHER"
);
}
SoladyPRNG prng = new SoladyPRNG(activeRaffle.prngState);
LiberoRewards_01.RaffleExt storage activeRaffleExt = _raffleExt[
raffleNr
];
uint256 drawTotalTickets = isPriority
? priorityTicketsLength
: activeRaffle.totalTickets;
drawTotalTickets -= activeRaffle.pickedRewards;
require(drawTotalTickets > 0, "RAFFLE_FINISHED_NO_MORE_TICKETS");
uint256 drawRounds = drawTotalTickets;
if (drawRounds > drawTotalTickets) drawRounds = drawTotalTickets;
if (drawRounds > cnt) drawRounds = cnt;
for (uint256 i = 0; i < drawRounds; i++) {
if (activeRaffle.nextRewardIx >= activeRaffle.totalRewards) {
break;
}
uint256 winnerIx = prng.random(drawTotalTickets);
Ticketing_01.Ticket memory winningTicket = activeRaffle
.tickets
.getValidTicketAtIx(isPriority, winnerIx);
if (winnerIx != drawTotalTickets - 1) {
activeRaffle.tickets.swapValidTickets(
isPriority,
winnerIx,
drawTotalTickets - 1
);
}
LiberoRewards_01.Reward memory reward = activeRaffle.rewards[
activeRaffle.nextRewardIx
];
uint32 rewardsPerWallet = activeRaffleExt.rewardsPerWallet[
winningTicket.wallet
] + 1;
activeRaffleExt.rewardsPerWallet[
winningTicket.wallet
] = rewardsPerWallet;
bool isSkipped = false;
if (rewardsPerWallet > activeRaffle.maxRewardsPerWallet) {
isSkipped = true;
} else {
activeRaffle.nextRewardIx++;
}
activeRaffle.winningTickets.push(
LiberoRewards_01.WinningTicket(winningTicket, reward, isSkipped)
);
if (!isSkipped) {
uint256 ticketKey = activeRaffle.tickets.getTicketKeyExt(
winningTicket
);
activeRaffleExt.winningTicketKeys[ticketKey] = true;
}
emit LiberoRewards_01.TicketPicked(
raffleNr,
uint32(activeRaffle.winningTickets.length),
uint32(winnerIx),
uint32(drawTotalTickets),
isSkipped,
isPriority,
reward.tokenId,
reward.tokenAmount,
winningTicket.tokenId,
winningTicket.wallet,
winningTicket.ticketId,
winningTicket.ticketNr,
winningTicket.reqNr
);
drawTotalTickets -= 1;
activeRaffle.pickedRewards += 1;
}
}
bool private _distributingRewards;
function _burnRewardIxInternal(
uint32 raffleNr,
uint32 ix
) private returns (bool success) {
require(!_distributingRewards);
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
if (activeRaffle.shouldDistributeRewards) {
_distributingRewards = true;
success = LiberoRewards_01.ext_burnRewardIxInternal(
raffleNr,
activeRaffle.winningTickets[ix],
activeRaffle.requirements
);
_distributingRewards = false;
}
}
function _sendRewardIxInternal(
uint32 raffleNr,
uint32 ix
) private returns (bool success) {
require(!_distributingRewards);
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
if (activeRaffle.shouldDistributeRewards) {
_distributingRewards = true;
success = LiberoRewards_01.ext_sendRewardIxInternal(
raffleNr,
activeRaffle.winningTickets[ix],
activeRaffle.rewardIf,
activeRaffle.rewardContract,
activeRaffle.mintContract,
activeRaffle.organizer
);
_distributingRewards = false;
}
}
function _distributeRewardIxInternal(uint32 raffleNr, uint32 ix) private {
bool success = _burnRewardIxInternal(raffleNr, ix);
if (success) {
success = _sendRewardIxInternal(raffleNr, ix);
}
}
function distributeRewards(uint32 raffleNr, uint32 cnt) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(activeRaffle.prngInitialized, "RAFFLE_PRNG_NOT_INITIALIZED");
require(
(activeRaffle.totalRewards == (activeRaffle.nextRewardIx)) ||
(activeRaffle.pickedRewards == activeRaffle.totalTickets),
"REWARDS_NOT_PICKED"
);
uint256 finalCnt = activeRaffle.distributeNextIx + cnt;
if (finalCnt > activeRaffle.winningTickets.length) {
finalCnt = activeRaffle.winningTickets.length;
}
require(
finalCnt > activeRaffle.distributeNextIx,
"REWARDS_DISTRIBUTED"
);
for (uint256 i = activeRaffle.distributeNextIx; i < finalCnt; i++) {
_distributeRewardIxInternal(raffleNr, uint32(i));
activeRaffle.distributeNextIx++;
}
}
function distributeRewardIx(uint32 raffleNr, uint32 ix) public onlyManager {
_distributeRewardIxInternal(raffleNr, ix);
}
function burnRewardIx(uint32 raffleNr, uint32 ix) public onlyManager {
_burnRewardIxInternal(raffleNr, ix);
}
function burnRaw(
address collection,
address owner,
uint8 rewardIf,
uint256 tokenId,
uint256 tokenAmount
) public onlyManager {
if (rewardIf == IF_ERC721) {
ERC721Burnable burn721 = ERC721Burnable(collection);
burn721.burn(tokenId);
} else if (rewardIf == IF_ERC1155) {
ERC1155Burnable burn1155 = ERC1155Burnable(collection);
burn1155.burn(owner, tokenId, tokenAmount);
} else if (rewardIf == IF_MANIFOLD1155) {
ManifoldERC1155Burnable burn1155 = ManifoldERC1155Burnable(
collection
);
uint256[] memory ids = new uint256[](1);
uint256[] memory values = new uint256[](1);
ids[0] = tokenId;
values[0] = tokenAmount;
burn1155.burn(owner, ids, values);
}
}
function transferRaw(
address collection,
address owner,
address recepient,
uint8 rewardIf,
uint256 tokenId,
uint256 tokenAmount
) public onlyManager {
if (rewardIf == IF_ERC721) {
IERC721 burn721 = IERC721(collection);
burn721.safeTransferFrom(owner, recepient, tokenId);
} else if (rewardIf == IF_ERC1155) {
IERC1155 burn1155 = IERC1155(collection);
burn1155.safeTransferFrom(
owner,
recepient,
tokenId,
tokenAmount,
""
);
}
}
function sendRewardIx(uint32 raffleNr, uint32 ix) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
if (activeRaffle.shouldDistributeRewards) {
require(
activeRaffle.distributeNextIx ==
activeRaffle.winningTickets.length,
"REWARDS_NOT_DISTRIBUTED"
);
}
_sendRewardIxInternal(raffleNr, ix);
}
bool private _refundingNonWinning;
function refundNonWinning(
uint32 raffleNr,
bool isPriority,
uint32 cnt
) public onlyManager {
require(!_refundingNonWinning, "REFUND_NON_WINNING_LOCKED");
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
require(activeRaffle.prngInitialized, "RAFFLE_PRNG_NOT_INITIALIZED");
require(
(activeRaffle.totalRewards == (activeRaffle.nextRewardIx)) ||
(activeRaffle.pickedRewards == activeRaffle.totalTickets),
"REWARDS_NOT_PICKED"
);
if (activeRaffle.shouldDistributeRewards) {
require(
activeRaffle.distributeNextIx ==
activeRaffle.winningTickets.length,
"REWARDS_NOT_DISTRIBUTED"
);
}
require(
activeRaffle.shouldRefundNonWinning,
"SHOULD_REFUND_NON_WINNING"
);
uint256 refundedIx = isPriority
? activeRaffle.refundedPriorityIx
: activeRaffle.refundedIx;
uint256 refundTicketsLen = activeRaffle.tickets.getValidTicketsLength(
isPriority
);
require(refundedIx < refundTicketsLen, "REFUND_NON_WINNING_FINISHED");
_refundingNonWinning = true;
LiberoRewards_01.RaffleExt storage activeRaffleExt = _raffleExt[
raffleNr
];
uint256 upToIx = refundedIx + cnt;
if (upToIx > refundTicketsLen) upToIx = refundTicketsLen;
for (uint256 i = refundedIx; i < upToIx; i++) {
Ticketing_01.Ticket memory ticket = activeRaffle
.tickets
.getValidTicketAtIx(isPriority, i);
uint256 ticketKey = activeRaffle.tickets.getTicketKeyExt(ticket);
if (!activeRaffleExt.winningTicketKeys[ticketKey]) {
uint8 reqNr = ticket.reqNr;
require(
reqNr < activeRaffle.requirements.length,
"TICKET_REFUND_NO_REQ_IX"
);
uint256 price = activeRaffle.requirements[reqNr].ticketPrice;
if (price > 0) {
bool success = false;
try
LiberoRewards_01.ext_payAny(ticket.wallet, price, 10000)
returns (bool sent) {
success = sent;
} catch {}
if (success) {
activeRaffle.fees -= price;
}
emit LiberoRewards_01.TicketRefundNonWinning(
raffleNr,
ticket.tokenId,
ticket.wallet,
ticket.ticketId,
ticket.ticketNr,
ticket.reqNr,
success,
price
);
}
}
}
if (isPriority) {
activeRaffle.refundedPriorityIx = upToIx;
} else {
activeRaffle.refundedIx = upToIx;
}
_refundingNonWinning = false;
}
function _checkRaffleDone(
LiberoRewards_01.Raffle memory activeRaffle
) public view {
require(activeRaffle.prngInitialized, "RAFFLE_PRNG_NOT_INITIALIZED");
if (activeRaffle.shouldDistributeRewards) {
require(
activeRaffle.distributeNextIx ==
activeRaffle.winningTickets.length,
"REWARDS_NOT_DISTRIBUTED"
);
}
require(
!activeRaffle.shouldRefundNonWinning ||
(activeRaffle.refundedPriorityIx ==
activeRaffle.tickets.getValidTicketsLength(true) &&
activeRaffle.refundedIx ==
activeRaffle.tickets.getValidTicketsLength(false)),
"SHOULD_REFUND_NON_WINNING"
);
}
function payoutFees(uint32 raffleNr) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
_checkRaffleDone(activeRaffle);
uint256 ownerFee = (activeRaffle.fees * activeRaffle.ownerFeePct) / 100;
uint256 ownerTip = (activeRaffle.tips * activeRaffle.ownerTipPct) / 100;
payable(owner()).transfer(ownerFee + ownerTip);
payable(activeRaffle.organizer).transfer(
activeRaffle.fees + activeRaffle.tips - ownerFee - ownerTip
);
activeRaffle.fees = 0;
activeRaffle.tips = 0;
}
function transferMintOwnership(uint32 raffleNr) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
if (activeRaffle.mintContract != address(0)) {
if (activeRaffle.rewardIf == IF_ERC721) {
LiberoERC721_01(activeRaffle.mintContract).transferOwnership(
activeRaffle.organizer
);
} else if (activeRaffle.rewardIf == IF_ERC1155) {
LiberoERC1155_01(activeRaffle.mintContract).transferOwnership(
activeRaffle.organizer
);
}
}
}
function batchMintManager(
uint32 raffleNr,
address[] memory to,
uint256[] memory tokenIds,
uint256[] memory tokenAmounts
) public onlyManager {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
LiberoRewards_01.ext_batchMint(
activeRaffle.rewardIf,
activeRaffle.mintContract,
to,
tokenIds,
tokenAmounts
);
}
function batchMintOwner(
uint32 raffleNr,
address[] memory to,
uint256[] memory tokenIds,
uint256[] memory tokenAmounts,
bytes memory signature
) public {
LiberoRewards_01.Raffle storage activeRaffle = _raffleInfo[raffleNr];
_checkRaffleDone(activeRaffle);
address recoveredSigner = LiberoRewards_01.ext_batchMintCheckSignature(
raffleNr,
to,
tokenIds,
tokenAmounts,
signature
);
require(
recoveredSigner == _manager,
"BATCH_MINT_NEEDS_VALID_SIGNATURE"
);
LiberoRewards_01.ext_batchMint(
activeRaffle.rewardIf,
activeRaffle.mintContract,
to,
tokenIds,
tokenAmounts
);
}
function withdraw(uint256 amount) public onlyOwner {
payable(owner()).transfer(amount);
}
function fund() public payable {}
}
文件 24 的 34:LiberoReward_01.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "./LiberoERC721_01.sol";
import "./LiberoERC1155_01.sol";
import "./Ticketing_01.sol";
import "./ManifoldBurnable.sol";
uint constant IF_NONE = 0;
uint constant IF_ERC721 = 1;
uint constant IF_ERC1155 = 2;
uint constant IF_MANIFOLD1155 = 3;
uint256 constant NO_REWARD = uint256(int256(-1));
library LiberoRewards_01 {
struct Raffle {
address organizer;
address rewardContract;
address mintContract;
uint32 availableRewards;
uint8 rewardIf;
Reward[] rewards;
Requirement[] requirements;
uint256 startAt;
uint256 endAt;
uint256 raffleAt;
uint256 sysTicketPrice;
uint16 ownerFeePct;
uint16 ownerTipPct;
uint256 tips;
uint256 fees;
Ticketing_01 tickets;
bool prngInitialized;
uint256 prngState;
uint256 nextRewardIx;
uint256 totalTickets;
uint256 totalRewards;
uint32 maxRewardsPerWallet;
uint256 pickedRewards;
WinningTicket[] winningTickets;
bool shouldDistributeRewards;
uint256 distributeNextIx;
bool shouldRefundNonWinning;
uint256 refundedPriorityIx;
uint256 refundedIx;
bool finished;
}
struct RaffleExt {
mapping(address => uint32) rewardsPerWallet;
mapping(uint256 => bool) winningTicketKeys;
}
event RaffleCreated(uint32 raffleNr, uint32 id);
event Payment(
uint32 raffleNr,
address wallet,
uint256 tip,
uint256 fee,
bool refund
);
event TicketPicked(
uint32 raffleNr,
uint32 winSeqNr,
uint32 drawIx,
uint32 drawFrom,
bool isSkipped,
bool isPriority,
uint256 rewardTokenId,
uint16 rewardTokenAmount,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr
);
struct WinningTicket {
Ticketing_01.Ticket ticket;
Reward reward;
bool skipped;
}
struct Reward {
uint256 tokenId;
uint16 tokenAmount;
}
struct Requirement {
uint8 burnIf;
uint16 burnTokenAmount;
address burnContract;
uint256 ticketPrice;
}
event RewardError(
uint32 raffleNr,
string error,
string reason,
uint256 rewardTokenId,
uint16 rewardTokenAmount,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr
);
event RewardSuccessful(
uint32 raffleNr,
uint256 rewardTokenId,
uint16 rewardTokenAmount,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr
);
event TicketRefundNonWinning(
uint32 raffleNr,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr,
bool success,
uint256 amount
);
function _rewardError(
uint32 raffleNr,
string memory message,
string memory reason,
WinningTicket memory winningTicket
) private {
emit RewardError(
raffleNr,
message,
reason,
winningTicket.reward.tokenId,
winningTicket.reward.tokenAmount,
winningTicket.ticket.tokenId,
winningTicket.ticket.wallet,
winningTicket.ticket.ticketId,
winningTicket.ticket.ticketNr,
winningTicket.ticket.reqNr
);
}
function ext_newRaffleValidateAndCheckSignature(
uint32 id,
uint256 payAmount,
address organizer,
uint32 totalTickets,
uint32 totalPriorityTickets,
uint32 maxTicketsPerWallet,
uint32 maxRewardsPerWallet,
uint32 availableRewards,
uint8 rewardIf,
address rewardContract,
string memory mintUri,
string memory mintName,
string memory mintSymbol,
bool shouldDistributeRewards,
bool shouldRefundNonWinning,
uint256 startAt,
uint256 endAt,
uint256 raffleAt,
uint256 sysTicketPrice,
uint16 ownerFeePct,
uint16 ownerTipPct,
LiberoRewards_01.Requirement[] memory requirements,
bytes memory signature
) public returns (address recoveredSigner) {
require(msg.value == payAmount, "MUST_PAY_EXACT_AMOUNT");
require(
(bytes(mintUri).length == 0 && rewardContract != address(0)) ||
(bytes(mintUri).length > 0 && rewardContract == address(0)),
"SET_EITHER_REWARD_OR_MINT"
);
require(availableRewards > 0, "MIN_1_REWARD");
require(ownerFeePct >= 0 && ownerFeePct <= 100, "OWNER_FEE_INVALID");
require(ownerTipPct >= 0 && ownerTipPct <= 100, "OWNER_TIP_INVALID");
require(startAt > block.timestamp, "SHOULD_START_IN_FUTURE");
require(endAt > startAt, "END_SHOULD_BE_AFTER_START");
require(raffleAt >= endAt, "RAFFLE_SHOULD_BE_AFTER_END");
bytes memory packed = abi.encodePacked(
id,
payAmount,
organizer,
totalTickets,
totalPriorityTickets,
maxTicketsPerWallet,
maxRewardsPerWallet,
availableRewards,
rewardIf,
rewardContract,
mintUri,
mintName,
mintSymbol,
shouldDistributeRewards,
shouldRefundNonWinning,
startAt,
endAt,
raffleAt,
sysTicketPrice,
ownerFeePct,
ownerTipPct
);
for (uint256 i = 0; i < requirements.length; i++) {
packed = abi.encodePacked(
packed,
requirements[i].burnIf,
requirements[i].burnTokenAmount,
requirements[i].burnContract,
requirements[i].ticketPrice
);
}
bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash(
packed
);
recoveredSigner = ECDSA.recover(ethSignedMessageHash, signature);
}
function ext_buyTicketsValidateAndCheckSignature(
uint32 raffleNr,
Raffle storage activeRaffle,
Ticketing_01.Ticket[] calldata toBuy,
Ticketing_01.Ticket[] calldata toReturn,
uint256 tip,
bytes memory signature
)
public
returns (
address recoveredSigner,
uint256 netPayAmount,
uint256 netRefundAmount
)
{
require(
block.timestamp >= activeRaffle.startAt &&
block.timestamp < activeRaffle.endAt,
"TICKET_SALE_NOT_ACTIVE"
);
uint256 expectedPayAmount = 0;
uint256 expectedRefundAmount = 0;
netPayAmount = 0;
netRefundAmount = 0;
for (uint256 i = 0; i < toBuy.length; i++) {
uint8 reqNr = toBuy[i].reqNr;
require(
reqNr < activeRaffle.requirements.length,
"BUY_REQUIREMENT_IX_NOT_FOUND"
);
uint256 price = activeRaffle.requirements[reqNr].ticketPrice;
expectedPayAmount += price;
}
for (uint256 i = 0; i < toReturn.length; i++) {
uint8 reqNr = toReturn[i].reqNr;
require(
reqNr < activeRaffle.requirements.length,
"RETURN_REQUIREMENT_IX_NOT_FOUND"
);
uint256 price = activeRaffle.requirements[reqNr].ticketPrice;
expectedRefundAmount += price;
}
if (expectedPayAmount > expectedRefundAmount) {
netPayAmount = expectedPayAmount - expectedRefundAmount;
} else {
netRefundAmount = expectedRefundAmount - expectedPayAmount;
}
require(
msg.value ==
netPayAmount +
(toBuy.length * activeRaffle.sysTicketPrice) +
tip,
"INVALID_PAYMENT_FOR_TICKETS"
);
bytes memory packed = abi.encodePacked(raffleNr);
for (uint256 i = 0; i < toBuy.length; i++) {
require(
msg.sender == address(toBuy[i].wallet),
"MUST_BUY_TICKET_FOR_SELF"
);
require(toBuy[i].valid, "MUST_BUY_VALID_TICKET");
packed = abi.encodePacked(
packed,
toBuy[i].tokenId,
toBuy[i].wallet,
toBuy[i].ticketId,
toBuy[i].ticketNr,
toBuy[i].reqNr,
toBuy[i].isPriority,
toBuy[i].valid
);
}
for (uint256 i = 0; i < toReturn.length; i++) {
require(
msg.sender == address(toReturn[i].wallet),
"MUST_RETURN_TICKET_FROM_SELF"
);
require(!toReturn[i].valid, "MUST_RETURN_NOT_VALID_TICKET");
packed = abi.encodePacked(
packed,
toReturn[i].tokenId,
toReturn[i].wallet,
toReturn[i].ticketId,
toReturn[i].ticketNr,
toReturn[i].reqNr,
toReturn[i].isPriority,
toReturn[i].valid
);
}
bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash(
packed
);
recoveredSigner = ECDSA.recover(ethSignedMessageHash, signature);
}
function ext_burnRewardIxInternal(
uint32 raffleNr,
WinningTicket calldata winningTicket,
Requirement[] calldata requirements
) public returns (bool success) {
if (!winningTicket.skipped) {
success = true;
if (requirements.length > 0) {
uint8 reqNr = winningTicket.ticket.reqNr;
if (reqNr <= requirements.length) {
Requirement memory requirement = requirements[reqNr];
if (requirement.burnIf == IF_ERC721) {
if (winningTicket.ticket.reqNr >= requirements.length) {
success = false;
_rewardError(
raffleNr,
"burn.erc721.error",
"TICKET_BURN_TOKEN_NOT_FOUND",
winningTicket
);
} else {
ERC721Burnable burn721 = ERC721Burnable(
requirements[winningTicket.ticket.reqNr]
.burnContract
);
try
burn721.burn(winningTicket.ticket.tokenId)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"burn.erc721.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"burn.erc721.error.0",
string(lowLevelData),
winningTicket
);
}
}
} else if (requirement.burnIf == IF_ERC1155) {
if (winningTicket.ticket.reqNr >= requirements.length) {
success = false;
_rewardError(
raffleNr,
"burn.erc1155.error",
"TICKET_BURN_TOKEN_NOT_FOUND",
winningTicket
);
} else {
ERC1155Burnable burn1155 = ERC1155Burnable(
requirements[winningTicket.ticket.reqNr]
.burnContract
);
try
burn1155.burn(
address(winningTicket.ticket.wallet),
winningTicket.ticket.tokenId,
requirements[winningTicket.ticket.reqNr]
.burnTokenAmount
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"burn.erc1155.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"burn.erc1155.error.0",
string(lowLevelData),
winningTicket
);
}
}
} else if (requirement.burnIf == IF_MANIFOLD1155) {
if (winningTicket.ticket.reqNr >= requirements.length) {
success = false;
_rewardError(
raffleNr,
"burn.erc1155.error",
"TICKET_BURN_TOKEN_NOT_FOUND",
winningTicket
);
} else {
ManifoldERC1155Burnable burn1155 = ManifoldERC1155Burnable(
requirements[winningTicket.ticket.reqNr]
.burnContract
);
uint256[] memory ids = new uint256[](1);
uint256[] memory values = new uint256[](1);
ids[0] = winningTicket.ticket.tokenId;
values[0] = requirements[winningTicket.ticket.reqNr]
.burnTokenAmount;
try
burn1155.burn(
address(winningTicket.ticket.wallet),
ids,
values
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"burn.manifold1155.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"burn.manifold1155.error.0",
string(lowLevelData),
winningTicket
);
}
}
}
} else {
success = false;
_rewardError(
raffleNr,
"burn.token.error",
"REQ_BURN_TOKEN_NOT_FOUND",
winningTicket
);
}
}
}
}
function ext_sendRewardIxInternal(
uint32 raffleNr,
WinningTicket calldata winningTicket,
uint8 rewardIf,
address rewardContract,
address mintContract,
address organizer
) public returns (bool success) {
if (!winningTicket.skipped) {
success = true;
if (mintContract != address(0)) {
if (rewardIf == IF_ERC721) {
LiberoERC721_01 mint721 = LiberoERC721_01(mintContract);
try
mint721.mintTo(
address(winningTicket.ticket.wallet),
winningTicket.reward.tokenId
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"mint721.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"mint721.error.0",
string(lowLevelData),
winningTicket
);
}
} else if (rewardIf == IF_ERC1155) {
LiberoERC1155_01 mint1155 = LiberoERC1155_01(mintContract);
try
mint1155.mint(
address(winningTicket.ticket.wallet),
winningTicket.reward.tokenId,
winningTicket.reward.tokenAmount,
""
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"mint1155.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"mint1155.error.0",
string(lowLevelData),
winningTicket
);
}
}
} else if (rewardContract != address(0)) {
if (rewardIf == IF_ERC721) {
IERC721 reward721 = IERC721(rewardContract);
try
reward721.safeTransferFrom(
organizer,
address(winningTicket.ticket.wallet),
winningTicket.reward.tokenId
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"transfer721.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"transfer721.error.0",
string(lowLevelData),
winningTicket
);
}
} else if (rewardIf == IF_ERC1155) {
IERC1155 reward1155 = IERC1155(rewardContract);
try
reward1155.safeTransferFrom(
organizer,
address(winningTicket.ticket.wallet),
winningTicket.reward.tokenId,
winningTicket.reward.tokenAmount,
""
)
{} catch Error(string memory reason) {
success = false;
_rewardError(
raffleNr,
"transfer1155.error",
reason,
winningTicket
);
} catch (bytes memory lowLevelData) {
success = false;
_rewardError(
raffleNr,
"transfer1155.error.0",
string(lowLevelData),
winningTicket
);
}
}
}
if (success) {
emit LiberoRewards_01.RewardSuccessful(
raffleNr,
winningTicket.reward.tokenId,
winningTicket.reward.tokenAmount,
winningTicket.ticket.tokenId,
winningTicket.ticket.wallet,
winningTicket.ticket.ticketId,
winningTicket.ticket.ticketNr,
winningTicket.ticket.reqNr
);
}
}
}
function ext_approveAwardInternal(
uint8 rewardIf,
address rewardContract,
address organizer,
Reward[] memory rewards
) public view {
bool approved = false;
if (rewardIf == IF_ERC721) {
IERC721 erc721 = IERC721(rewardContract);
if (erc721.isApprovedForAll(organizer, address(this))) {
approved = true;
} else {
for (uint256 i = 0; i < rewards.length; i++) {
if (
address(this) == erc721.getApproved(rewards[i].tokenId)
) {
approved = true;
}
}
}
} else if (rewardIf == IF_ERC1155) {
IERC1155 erc1155 = IERC1155(rewardContract);
if (erc1155.isApprovedForAll(organizer, address(this))) {
approved = true;
}
}
require(approved, "REWARD_NOT_APPROVED");
}
function ext_batchMint(
uint8 rewardIf,
address mintContract,
address[] memory to,
uint256[] memory tokenIds,
uint256[] memory tokenAmounts
) public {
require(to.length == tokenIds.length, "BATCH_MINT_L1");
require(to.length == tokenAmounts.length, "BATCH_MINT_L2");
if (mintContract != address(0)) {
if (rewardIf == IF_ERC721) {
LiberoERC721_01 mint721 = LiberoERC721_01(mintContract);
for (uint256 i = 0; i < to.length; i++) {
mint721.mintTo(to[i], tokenIds[i]);
}
} else if (rewardIf == IF_ERC1155) {
LiberoERC1155_01 mint1155 = LiberoERC1155_01(mintContract);
for (uint256 i = 0; i < to.length; i++) {
mint1155.mint(to[i], tokenIds[i], tokenAmounts[i], "");
}
}
}
}
function ext_batchMintCheckSignature(
uint32 raffleNr,
address[] memory to,
uint256[] memory tokenIds,
uint256[] memory tokenAmounts,
bytes memory signature
) public pure returns (address recoveredSigner) {
require(to.length == tokenIds.length, "BATCH_MINT_L1");
require(to.length == tokenAmounts.length, "BATCH_MINT_L2");
bytes memory packed = abi.encodePacked(raffleNr);
for (uint256 i = 0; i < to.length; i++) {
packed = abi.encodePacked(
packed,
to[i],
tokenIds[i],
tokenAmounts[i]
);
}
bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash(
packed
);
recoveredSigner = ECDSA.recover(ethSignedMessageHash, signature);
}
function ext_payAny(
address to,
uint256 amount,
uint32 gasLimit
) public returns (bool) {
(bool sent, ) = payable(to).call{gas: gasLimit, value: amount}("");
return sent;
}
}
文件 25 的 34:ManifoldBurnable.sol
pragma solidity ^0.8.24;
interface ManifoldERC1155Burnable {
function burn(
address account,
uint256[] calldata tokenIds,
uint256[] calldata amounts
) external;
}
文件 26 的 34:Math.sol
pragma solidity ^0.8.20;
library Math {
error MathOverflowedMulDiv();
enum Rounding {
Floor,
Ceil,
Trunc,
Expand
}
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
return a / b;
}
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0 = x * y;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (0 - denominator);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
文件 27 的 34:MessageHashUtils.sol
pragma solidity ^0.8.20;
import {Strings} from "../Strings.sol";
library MessageHashUtils {
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, messageHash)
digest := keccak256(0x00, 0x3c)
}
}
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
assembly {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}
文件 28 的 34:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 29 的 34:SignedMath.sol
pragma solidity ^0.8.20;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 30 的 34:StorageSlot.sol
pragma solidity ^0.8.20;
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly {
r.slot := store.slot
}
}
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := store.slot
}
}
}
文件 31 的 34:Strings.sol
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
error StringsInsufficientHexLength(uint256 value, uint256 length);
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 32 的 34:TicketingFactory_01.sol
pragma solidity ^0.8.24;
import "./Ticketing_01.sol";
contract TicketingFactory_01 {
function deployTicketing(
address initialOwner,
uint256 _totalTickets,
uint256 _totalPriorityTickets,
uint256 _maxTicketsPerWallet
) public returns (Ticketing_01 contractAddress) {
Ticketing_01 ticketing = new Ticketing_01(
initialOwner,
_totalTickets,
_totalPriorityTickets,
_maxTicketsPerWallet
);
return ticketing;
}
}
文件 33 的 34:Ticketing_01.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Ticketing_01 is Ownable {
struct Ticket {
uint256 tokenId;
address wallet;
uint64 ticketId;
uint16 ticketNr;
uint8 reqNr;
bool isPriority;
bool valid;
}
mapping(uint256 => bool) public tickets;
mapping(address => uint256[]) public walletTickets;
mapping(uint256 => uint256) public ticketIndexInAllTickets;
Ticket[] private allTickets;
uint256 private totalTickets;
uint256 private totalPriorityTickets;
uint256 private maxTicketsPerWallet;
uint256 private totalTicketsSold;
uint256 private totalPriorityTicketsSold;
uint256 returnedTickets;
event TicketBought(
uint32 raffleNr,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr,
bool isPriority
);
event TicketReturned(
uint32 raffleNr,
uint256 tokenId,
address wallet,
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr,
bool isPriority
);
constructor(
address initialOwner,
uint256 _totalTickets,
uint256 _totalPriorityTickets,
uint256 _maxTicketsPerWallet
) Ownable(initialOwner) {
totalTickets = _totalTickets;
totalPriorityTickets = _totalPriorityTickets;
maxTicketsPerWallet = _maxTicketsPerWallet;
}
function getTicketKey(
uint64 ticketId,
uint16 ticketNr,
uint8 reqNr
) internal pure returns (uint256) {
return
(uint256(ticketId) << 32) |
(uint256(ticketNr) << 16) |
uint256(reqNr) ;
}
function buyTickets(
uint32 raffleNr,
Ticket[] calldata ticketsToBuy
) external onlyOwner {
require(
totalTicketsSold + ticketsToBuy.length <= totalTickets,
"MAX_TICKETS_REACHED"
);
require(ticketsToBuy.length > 0, "NO_TICKETS");
require(validatedUpTo == 0, "ALREADY_VALIDATED");
for (uint256 i = 0; i < ticketsToBuy.length; i++) {
Ticket memory ticket = ticketsToBuy[i];
require(ticket.valid, "TICKET_VALID");
if (ticket.isPriority) {
require(
totalPriorityTicketsSold + 1 <= totalPriorityTickets,
"MAX_PRIORITY_TICKETS_REACHED"
);
totalPriorityTicketsSold++;
}
uint256 ticketKey = getTicketKey(
ticket.ticketId,
ticket.ticketNr,
ticket.reqNr
);
require(
walletTickets[address(ticket.wallet)].length <
maxTicketsPerWallet,
"MAX_TICKETS_PER_WALLET"
);
require(!tickets[ticketKey], "TICKET_ALREADY_EXISTS");
tickets[ticketKey] = true;
walletTickets[address(ticket.wallet)].push(ticketKey);
uint256 index = ticketIndexInAllTickets[ticketKey];
if (allTickets.length > 0 && index > 0) {
returnedTickets--;
allTickets[index] = ticket;
} else {
ticketIndexInAllTickets[ticketKey] = allTickets.length;
allTickets.push(ticket);
}
totalTicketsSold++;
emit TicketBought(
raffleNr,
ticket.tokenId,
ticket.wallet,
ticket.ticketId,
ticket.ticketNr,
ticket.reqNr,
ticket.isPriority
);
}
}
function returnTickets(
uint32 raffleNr,
Ticket[] calldata ticketsToReturn
) external onlyOwner {
require(ticketsToReturn.length > 0, "NO_TICKETS");
require(validatedUpTo == 0, "ALREADY_VALIDATED");
for (uint256 i = 0; i < ticketsToReturn.length; i++) {
Ticket memory ticket = ticketsToReturn[i];
require(!ticket.valid, "TICKET_NOT_VALID");
uint256 ticketKey = getTicketKey(
ticket.ticketId,
ticket.ticketNr,
ticket.reqNr
);
require(
isOwnerOfTicket(address(ticket.wallet), ticketKey),
"ONLY_OWNER_CAN_RETURN"
);
require(tickets[ticketKey], "CANT_RETURN_TICKET");
tickets[ticketKey] = false;
uint256 index = ticketIndexInAllTickets[ticketKey];
require(
allTickets[index].isPriority == ticket.isPriority,
"PRIORITY_NOT_SAME"
);
allTickets[index].valid = false;
address wallet = address(ticket.wallet);
uint256 length = walletTickets[wallet].length;
for (uint256 j = 0; j < length; j++) {
if (walletTickets[wallet][j] == ticketKey) {
walletTickets[wallet][j] = walletTickets[wallet][
length - 1
];
walletTickets[wallet].pop();
break;
}
}
totalTicketsSold--;
if (ticket.isPriority) {
totalPriorityTicketsSold--;
}
returnedTickets++;
emit TicketReturned(
raffleNr,
ticket.tokenId,
ticket.wallet,
ticket.ticketId,
ticket.ticketNr,
ticket.reqNr,
ticket.isPriority
);
}
}
function isOwnerOfTicket(
address wallet,
uint256 ticketKey
) internal view returns (bool) {
uint256[] memory walletTicketKeys = walletTickets[wallet];
for (uint256 i = 0; i < walletTicketKeys.length; i++) {
if (walletTicketKeys[i] == ticketKey) {
return true;
}
}
return false;
}
function getWalletTickets(
address wallet
) external view returns (Ticket[] memory) {
require(owner() == _msgSender(), "ONLY_OWNER");
uint256[] memory walletTicketKeys = walletTickets[wallet];
Ticket[] memory result = new Ticket[](walletTicketKeys.length);
for (uint256 i = 0; i < walletTicketKeys.length; i++) {
uint256 index = ticketIndexInAllTickets[walletTicketKeys[i]];
result[i] = allTickets[index];
}
return result;
}
bool private validated;
uint256 private validatedUpTo;
Ticket[] private validPriorityTickets;
Ticket[] private validTickets;
function validateTickets(uint256 n) external onlyOwner {
require(!validated, "ALREADY_VALIDATED");
uint256 end = validatedUpTo + n;
if (end > allTickets.length) {
end = allTickets.length;
}
for (uint256 i = validatedUpTo; i < end; i++) {
Ticket memory ticket = allTickets[i];
if (ticket.valid) {
if (ticket.isPriority) {
validPriorityTickets.push(ticket);
} else {
validTickets.push(ticket);
}
}
}
validatedUpTo = end;
if (validatedUpTo == allTickets.length) {
validated = true;
}
}
function getTotalTicketsSold() public view returns (uint256) {
require(owner() == _msgSender(), "ONLY_OWNER");
return totalTicketsSold;
}
function getAllTicketsLength() public view returns (uint256) {
require(owner() == _msgSender(), "ONLY_OWNER");
return allTickets.length;
}
function getTicketsValidated() public view returns (bool) {
require(owner() == _msgSender(), "ONLY_OWNER");
return validated;
}
function getValidTicketsLength(
bool isPriority
) public view returns (uint256) {
require(owner() == _msgSender(), "ONLY_OWNER");
return isPriority ? validPriorityTickets.length : validTickets.length;
}
function getValidTicketAtIx(
bool isPriority,
uint256 ix
) public view returns (Ticket memory) {
require(owner() == _msgSender(), "ONLY_OWNER");
require(validated, "NOT_VALIDATED");
return isPriority ? validPriorityTickets[ix] : validTickets[ix];
}
function swapValidTickets(
bool isPriority,
uint256 fromIx,
uint256 toIx
) public {
require(owner() == _msgSender(), "ONLY_OWNER");
require(validated, "NOT_VALIDATED");
if (isPriority) {
Ticket memory ticket = validPriorityTickets[fromIx];
validPriorityTickets[fromIx] = validPriorityTickets[toIx];
validPriorityTickets[toIx] = ticket;
} else {
Ticket memory ticket = validTickets[fromIx];
validTickets[fromIx] = validTickets[toIx];
validTickets[toIx] = ticket;
}
}
function getAllTicketInfo() public view returns (Ticket[] memory) {
require(owner() == _msgSender(), "ONLY_OWNER");
return allTickets;
}
function getTicketAt(uint256 ix) public view returns (Ticket memory) {
require(owner() == _msgSender(), "ONLY_OWNER");
return allTickets[ix];
}
function getTicketValidationInfo()
public
view
returns (
uint256 _validatedUpTo,
bool _validated,
uint256 _totalTickets,
uint256 _totalPriorityTickets,
uint256 _maxTicketsPerWallet,
uint256 _totalTicketsSold,
uint256 _returnedTickets
)
{
require(owner() == _msgSender(), "ONLY_OWNER");
return (
validatedUpTo,
validated,
totalTickets,
totalPriorityTickets,
maxTicketsPerWallet,
totalTicketsSold,
returnedTickets
);
}
function getTicketKeyExt(
Ticket memory ticket
) public view returns (uint256) {
require(owner() == _msgSender(), "ONLY_OWNER");
return getTicketKey(ticket.ticketId, ticket.ticketNr, ticket.reqNr);
}
}
文件 34 的 34:draft-IERC6093.sol
pragma solidity ^0.8.20;
interface IERC20Errors {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidSpender(address spender);
}
interface IERC721Errors {
error ERC721InvalidOwner(address owner);
error ERC721NonexistentToken(uint256 tokenId);
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
error ERC721InvalidSender(address sender);
error ERC721InvalidReceiver(address receiver);
error ERC721InsufficientApproval(address operator, uint256 tokenId);
error ERC721InvalidApprover(address approver);
error ERC721InvalidOperator(address operator);
}
interface IERC1155Errors {
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
error ERC1155InvalidSender(address sender);
error ERC1155InvalidReceiver(address receiver);
error ERC1155MissingApprovalForAll(address operator, address owner);
error ERC1155InvalidApprover(address approver);
error ERC1155InvalidOperator(address operator);
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
{
"compilationTarget": {
"contracts/LiberoRaffle_01.sol": "LiberoRaffle_01"
},
"evmVersion": "paris",
"libraries": {
":__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"liberoMintFactory","type":"address"},{"internalType":"address","name":"ticketingFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"ERC1155Deployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"ERC721Deployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"raffleNr","type":"uint32"},{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"tip","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"bool","name":"refund","type":"bool"}],"name":"Payment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"raffleNr","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"id","type":"uint32"}],"name":"RaffleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"raffleNr","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"winSeqNr","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"drawIx","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"drawFrom","type":"uint32"},{"indexed":false,"internalType":"bool","name":"isSkipped","type":"bool"},{"indexed":false,"internalType":"bool","name":"isPriority","type":"bool"},{"indexed":false,"internalType":"uint256","name":"rewardTokenId","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"rewardTokenAmount","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint64","name":"ticketId","type":"uint64"},{"indexed":false,"internalType":"uint16","name":"ticketNr","type":"uint16"},{"indexed":false,"internalType":"uint8","name":"reqNr","type":"uint8"}],"name":"TicketPicked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"raffleNr","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint64","name":"ticketId","type":"uint64"},{"indexed":false,"internalType":"uint16","name":"ticketNr","type":"uint16"},{"indexed":false,"internalType":"uint8","name":"reqNr","type":"uint8"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TicketRefundNonWinning","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"organizer","type":"address"},{"internalType":"address","name":"rewardContract","type":"address"},{"internalType":"address","name":"mintContract","type":"address"},{"internalType":"uint32","name":"availableRewards","type":"uint32"},{"internalType":"uint8","name":"rewardIf","type":"uint8"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward[]","name":"rewards","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"burnIf","type":"uint8"},{"internalType":"uint16","name":"burnTokenAmount","type":"uint16"},{"internalType":"address","name":"burnContract","type":"address"},{"internalType":"uint256","name":"ticketPrice","type":"uint256"}],"internalType":"struct LiberoRewards_01.Requirement[]","name":"requirements","type":"tuple[]"},{"internalType":"uint256","name":"startAt","type":"uint256"},{"internalType":"uint256","name":"endAt","type":"uint256"},{"internalType":"uint256","name":"raffleAt","type":"uint256"},{"internalType":"uint256","name":"sysTicketPrice","type":"uint256"},{"internalType":"uint16","name":"ownerFeePct","type":"uint16"},{"internalType":"uint16","name":"ownerTipPct","type":"uint16"},{"internalType":"uint256","name":"tips","type":"uint256"},{"internalType":"uint256","name":"fees","type":"uint256"},{"internalType":"contract Ticketing_01","name":"tickets","type":"address"},{"internalType":"bool","name":"prngInitialized","type":"bool"},{"internalType":"uint256","name":"prngState","type":"uint256"},{"internalType":"uint256","name":"nextRewardIx","type":"uint256"},{"internalType":"uint256","name":"totalTickets","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint32","name":"maxRewardsPerWallet","type":"uint32"},{"internalType":"uint256","name":"pickedRewards","type":"uint256"},{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket","name":"ticket","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward","name":"reward","type":"tuple"},{"internalType":"bool","name":"skipped","type":"bool"}],"internalType":"struct LiberoRewards_01.WinningTicket[]","name":"winningTickets","type":"tuple[]"},{"internalType":"bool","name":"shouldDistributeRewards","type":"bool"},{"internalType":"uint256","name":"distributeNextIx","type":"uint256"},{"internalType":"bool","name":"shouldRefundNonWinning","type":"bool"},{"internalType":"uint256","name":"refundedPriorityIx","type":"uint256"},{"internalType":"uint256","name":"refundedIx","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"}],"internalType":"struct LiberoRewards_01.Raffle","name":"activeRaffle","type":"tuple"}],"name":"_checkRaffleDone","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"from","type":"uint256"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward[]","name":"rewards","type":"tuple[]"}],"name":"addRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"}],"name":"batchMintManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"batchMintOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"rewardIf","type":"uint8"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"burnRaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint32","name":"ix","type":"uint32"}],"name":"burnRewardIx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket[]","name":"toBuy","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket[]","name":"toReturn","type":"tuple[]"},{"internalType":"uint256","name":"tip","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"buyTickets","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint32","name":"ix","type":"uint32"}],"name":"distributeRewardIx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint32","name":"cnt","type":"uint32"}],"name":"distributeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"}],"name":"getRaffleInfo","outputs":[{"components":[{"internalType":"address","name":"organizer","type":"address"},{"internalType":"address","name":"rewardContract","type":"address"},{"internalType":"address","name":"mintContract","type":"address"},{"internalType":"uint32","name":"availableRewards","type":"uint32"},{"internalType":"uint8","name":"rewardIf","type":"uint8"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward[]","name":"rewards","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"burnIf","type":"uint8"},{"internalType":"uint16","name":"burnTokenAmount","type":"uint16"},{"internalType":"address","name":"burnContract","type":"address"},{"internalType":"uint256","name":"ticketPrice","type":"uint256"}],"internalType":"struct LiberoRewards_01.Requirement[]","name":"requirements","type":"tuple[]"},{"internalType":"uint256","name":"startAt","type":"uint256"},{"internalType":"uint256","name":"endAt","type":"uint256"},{"internalType":"uint256","name":"raffleAt","type":"uint256"},{"internalType":"uint256","name":"sysTicketPrice","type":"uint256"},{"internalType":"uint16","name":"ownerFeePct","type":"uint16"},{"internalType":"uint16","name":"ownerTipPct","type":"uint16"},{"internalType":"uint256","name":"tips","type":"uint256"},{"internalType":"uint256","name":"fees","type":"uint256"},{"internalType":"contract Ticketing_01","name":"tickets","type":"address"},{"internalType":"bool","name":"prngInitialized","type":"bool"},{"internalType":"uint256","name":"prngState","type":"uint256"},{"internalType":"uint256","name":"nextRewardIx","type":"uint256"},{"internalType":"uint256","name":"totalTickets","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint32","name":"maxRewardsPerWallet","type":"uint32"},{"internalType":"uint256","name":"pickedRewards","type":"uint256"},{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket","name":"ticket","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward","name":"reward","type":"tuple"},{"internalType":"bool","name":"skipped","type":"bool"}],"internalType":"struct LiberoRewards_01.WinningTicket[]","name":"winningTickets","type":"tuple[]"},{"internalType":"bool","name":"shouldDistributeRewards","type":"bool"},{"internalType":"uint256","name":"distributeNextIx","type":"uint256"},{"internalType":"bool","name":"shouldRefundNonWinning","type":"bool"},{"internalType":"uint256","name":"refundedPriorityIx","type":"uint256"},{"internalType":"uint256","name":"refundedIx","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"}],"internalType":"struct LiberoRewards_01.Raffle","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"}],"name":"getRaffleInfoCnt","outputs":[{"internalType":"uint256","name":"rewardsLen","type":"uint256"},{"internalType":"uint256","name":"ticketsLen","type":"uint256"},{"internalType":"uint256","name":"ticketsValidPriorityLen","type":"uint256"},{"internalType":"uint256","name":"ticketsValidLen","type":"uint256"},{"internalType":"uint256","name":"winningTicketsLen","type":"uint256"},{"internalType":"bool","name":"validated","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"fromIx","type":"uint256"},{"internalType":"uint256","name":"toIx","type":"uint256"}],"name":"getRaffleInfoRewards","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"address","name":"wallet","type":"address"}],"name":"getRaffleInfoRewardsPerWallet","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket","name":"ticket","type":"tuple"}],"name":"getRaffleInfoTicketKeyExt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"}],"name":"getRaffleInfoTicketValidationInfo","outputs":[{"internalType":"uint256","name":"_validatedUntil","type":"uint256"},{"internalType":"bool","name":"_validated","type":"bool"},{"internalType":"uint256","name":"_totalTickets","type":"uint256"},{"internalType":"uint256","name":"_totalPriorityTickets","type":"uint256"},{"internalType":"uint256","name":"_maxTicketsPerWallet","type":"uint256"},{"internalType":"uint256","name":"_totalTicketsSold","type":"uint256"},{"internalType":"uint256","name":"_returnedTickets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"fromIx","type":"uint256"},{"internalType":"uint256","name":"toIx","type":"uint256"}],"name":"getRaffleInfoTickets","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"uint256","name":"fromIx","type":"uint256"},{"internalType":"uint256","name":"toIx","type":"uint256"}],"name":"getRaffleInfoValidTickets","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket","name":"ticket","type":"tuple"}],"name":"getRaffleInfoWinningTicketKeys","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"fromIx","type":"uint256"},{"internalType":"uint256","name":"toIx","type":"uint256"}],"name":"getRaffleInfoWinningTickets","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint64","name":"ticketId","type":"uint64"},{"internalType":"uint16","name":"ticketNr","type":"uint16"},{"internalType":"uint8","name":"reqNr","type":"uint8"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct Ticketing_01.Ticket","name":"ticket","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint16","name":"tokenAmount","type":"uint16"}],"internalType":"struct LiberoRewards_01.Reward","name":"reward","type":"tuple"},{"internalType":"bool","name":"skipped","type":"bool"}],"internalType":"struct LiberoRewards_01.WinningTicket[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint256","name":"payAmount","type":"uint256"},{"internalType":"address","name":"organizer","type":"address"},{"internalType":"uint32","name":"totalTickets","type":"uint32"},{"internalType":"uint32","name":"totalPriorityTickets","type":"uint32"},{"internalType":"uint32","name":"maxTicketsPerWallet","type":"uint32"},{"internalType":"uint32","name":"maxRewardsPerWallet","type":"uint32"},{"internalType":"uint32","name":"availableRewards","type":"uint32"},{"internalType":"uint8","name":"rewardIf","type":"uint8"},{"internalType":"address","name":"rewardContract","type":"address"},{"internalType":"string","name":"mintUri","type":"string"},{"internalType":"string","name":"mintName","type":"string"},{"internalType":"string","name":"mintSymbol","type":"string"},{"internalType":"bool","name":"shouldDistributeRewards","type":"bool"},{"internalType":"bool","name":"shouldRefundNonWinning","type":"bool"},{"internalType":"uint256","name":"startAt","type":"uint256"},{"internalType":"uint256","name":"endAt","type":"uint256"},{"internalType":"uint256","name":"raffleAt","type":"uint256"},{"internalType":"uint256","name":"sysTicketPrice","type":"uint256"},{"internalType":"uint16","name":"ownerFeePct","type":"uint16"},{"internalType":"uint16","name":"ownerTipPct","type":"uint16"},{"components":[{"internalType":"uint8","name":"burnIf","type":"uint8"},{"internalType":"uint16","name":"burnTokenAmount","type":"uint16"},{"internalType":"address","name":"burnContract","type":"address"},{"internalType":"uint256","name":"ticketPrice","type":"uint256"}],"internalType":"struct LiberoRewards_01.Requirement[]","name":"requirements","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"newRaffle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"}],"name":"payoutFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"uint256","name":"cnt","type":"uint256"}],"name":"raffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"bool","name":"isPriority","type":"bool"},{"internalType":"uint32","name":"cnt","type":"uint32"}],"name":"refundNonWinning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"seed","type":"uint256"}],"name":"seedRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint32","name":"ix","type":"uint32"}],"name":"sendRewardIx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"}],"name":"transferMintOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"recepient","type":"address"},{"internalType":"uint8","name":"rewardIf","type":"uint8"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"transferRaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"raffleNr","type":"uint32"},{"internalType":"uint256","name":"cnt","type":"uint256"}],"name":"validateTickets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]