编译器
0.8.24+commit.e11b9ed9
文件 1 的 33:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 33:Array.sol
pragma solidity ^0.8.0;
library Array {
function KeepNElementsInArray(uint256[] memory _arr, uint256 _n)
internal
pure
returns (uint256[] memory newArray)
{
if (_arr.length == _n) return _arr;
require(_arr.length > _n, "can't cut more then got");
newArray = new uint256[](_n);
for (uint256 i = 0; i < _n; ++i) {
newArray[i] = _arr[i];
}
return newArray;
}
function KeepNElementsInArray(address[] memory _arr, uint256 _n)
internal
pure
returns (address[] memory newArray)
{
if (_arr.length == _n) return _arr;
require(_arr.length > _n, "can't cut more then got");
newArray = new address[](_n);
for (uint256 i = 0; i < _n; ++i) {
newArray[i] = _arr[i];
}
return newArray;
}
function isArrayOrdered(uint256[] memory _arr)
internal
pure
returns (bool)
{
require(_arr.length > 0, "array should be greater than zero");
uint256 temp = _arr[0];
for (uint256 i = 1; i < _arr.length; ++i) {
if (temp > _arr[i]) {
return false;
}
temp = _arr[i];
}
return true;
}
function getArraySum(uint256[] memory _array)
internal
pure
returns (uint256)
{
uint256 sum = 0;
for (uint256 i = 0; i < _array.length; ++i) {
sum = sum + _array[i];
}
return sum;
}
function isInArray(address[] memory _arr, address _elem)
internal
pure
returns (bool)
{
for (uint256 i = 0; i < _arr.length; ++i) {
if (_arr[i] == _elem) return true;
}
return false;
}
function addIfNotExsist(address[] storage _arr, address _elem) internal {
if (!Array.isInArray(_arr, _elem)) {
_arr.push(_elem);
}
}
}
文件 3 的 33:Context.sol
pragma solidity ^0.8.0;
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;
}
}
文件 4 的 33:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 33:ERC165Checker.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
library ERC165Checker {
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
function supportsERC165(address account) internal view returns (bool) {
return
supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
!supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
}
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
}
function getSupportedInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool[] memory) {
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
if (supportsERC165(account)) {
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
if (!supportsERC165(account)) {
return false;
}
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
return false;
}
}
return true;
}
function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}
文件 6 的 33:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => 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 override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
owner = ERC721.ownerOf(tokenId);
delete _tokenApprovals[tokenId];
unchecked {
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
delete _tokenApprovals[tokenId];
unchecked {
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}
文件 7 的 33:ERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
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 override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual override {
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
if (batchSize > 1) {
revert("ERC721Enumerable: consecutive transfers not supported");
}
uint256 tokenId = firstTokenId;
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_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 = ERC721.balanceOf(from) - 1;
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();
}
}
文件 8 的 33:FirewallConsumer.sol
pragma solidity ^0.8;
import {FirewallConsumerBase} from "./FirewallConsumerBase.sol";
contract FirewallConsumer is FirewallConsumerBase(address(0), msg.sender) {
}
文件 9 的 33:FirewallConsumerBase.sol
pragma solidity ^0.8;
import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IFirewall} from "./interfaces/IFirewall.sol";
import {IFirewallConsumer} from "./interfaces/IFirewallConsumer.sol";
contract FirewallConsumerBase is IFirewallConsumer, Context {
bytes32 private constant FIREWALL_STORAGE_SLOT = bytes32(uint256(keccak256("eip1967.firewall")) - 1);
bytes32 private constant FIREWALL_ADMIN_STORAGE_SLOT = bytes32(uint256(keccak256("eip1967.firewall.admin")) - 1);
bytes32 private constant NEW_FIREWALL_ADMIN_STORAGE_SLOT = bytes32(uint256(keccak256("eip1967.new.firewall.admin")) - 1);
bytes4 private constant SUPPORTS_APPROVE_VIA_SIGNATURE_INTERFACE_ID = bytes4(0x0c908cff);
bytes32 private constant APPROVED_TARGETS_MAPPING_SLOT = bytes32(uint256(keccak256("eip1967.approved.targets")) - 1);
event FirewallAdminUpdated(address newAdmin);
event FirewallUpdated(address newFirewall);
modifier firewallProtected() {
address firewall = _getAddressBySlot(FIREWALL_STORAGE_SLOT);
if (firewall == address(0)) {
_;
return;
}
uint256 value = _msgValue();
IFirewall(firewall).preExecution(_msgSender(), _msgData(), value);
_;
IFirewall(firewall).postExecution(_msgSender(), _msgData(), value);
}
modifier firewallProtectedCustom(bytes memory data) {
address firewall = _getAddressBySlot(FIREWALL_STORAGE_SLOT);
if (firewall == address(0)) {
_;
return;
}
uint256 value = _msgValue();
IFirewall(firewall).preExecution(_msgSender(), data, value);
_;
IFirewall(firewall).postExecution(_msgSender(), data, value);
}
modifier firewallProtectedSig(bytes4 selector) {
address firewall = _getAddressBySlot(FIREWALL_STORAGE_SLOT);
if (firewall == address(0)) {
_;
return;
}
uint256 value = _msgValue();
IFirewall(firewall).preExecution(_msgSender(), abi.encodePacked(selector), value);
_;
IFirewall(firewall).postExecution(_msgSender(), abi.encodePacked(selector), value);
}
modifier invariantProtected() {
address firewall = _getAddressBySlot(FIREWALL_STORAGE_SLOT);
if (firewall == address(0)) {
_;
return;
}
uint256 value = _msgValue();
bytes32[] memory storageSlots = IFirewall(firewall).preExecutionPrivateInvariants(_msgSender(), _msgData(), value);
bytes32[] memory preValues = _readStorage(storageSlots);
_;
bytes32[] memory postValues = _readStorage(storageSlots);
IFirewall(firewall).postExecutionPrivateInvariants(_msgSender(), _msgData(), value, preValues, postValues);
}
modifier onlyApprovedTarget(address target) {
bytes32 _slot = keccak256(abi.encode(APPROVED_TARGETS_MAPPING_SLOT, target));
bool isApprovedTarget = _getValueBySlot(_slot) != bytes32(0);
require(isApprovedTarget, "FirewallConsumer: Not approved target");
require(ERC165Checker.supportsERC165InterfaceUnchecked(target, SUPPORTS_APPROVE_VIA_SIGNATURE_INTERFACE_ID));
_;
}
modifier onlyFirewallAdmin() {
require(msg.sender == _getAddressBySlot(FIREWALL_ADMIN_STORAGE_SLOT), "FirewallConsumer: not firewall admin");
_;
}
constructor(
address _firewall,
address _firewallAdmin
) {
_setAddressBySlot(FIREWALL_STORAGE_SLOT, _firewall);
_setAddressBySlot(FIREWALL_ADMIN_STORAGE_SLOT, _firewallAdmin);
}
function safeFunctionCall(
address target,
bytes calldata targetPayload,
bytes calldata data
) external payable onlyApprovedTarget(target) {
(bool success, ) = target.call(targetPayload);
require(success);
require(msg.sender == _msgSender(), "FirewallConsumer: No meta transactions");
Address.functionDelegateCall(address(this), data);
}
function setApprovedTarget(address target, bool status) external onlyFirewallAdmin {
bytes32 _slot = keccak256(abi.encode(APPROVED_TARGETS_MAPPING_SLOT, target));
assembly {
sstore(_slot, status)
}
}
function firewallAdmin() external override view returns (address) {
return _getAddressBySlot(FIREWALL_ADMIN_STORAGE_SLOT);
}
function setFirewall(address _firewall) external onlyFirewallAdmin {
_setAddressBySlot(FIREWALL_STORAGE_SLOT, _firewall);
emit FirewallUpdated(_firewall);
}
function setFirewallAdmin(address _firewallAdmin) external onlyFirewallAdmin {
require(_firewallAdmin != address(0), "FirewallConsumer: zero address");
_setAddressBySlot(NEW_FIREWALL_ADMIN_STORAGE_SLOT, _firewallAdmin);
}
function acceptFirewallAdmin() external {
require(msg.sender == _getAddressBySlot(NEW_FIREWALL_ADMIN_STORAGE_SLOT), "FirewallConsumer: not new admin");
_setAddressBySlot(FIREWALL_ADMIN_STORAGE_SLOT, msg.sender);
emit FirewallAdminUpdated(msg.sender);
}
function _msgValue() internal view returns (uint256 value) {
assembly {
value := callvalue()
}
}
function _readStorage(bytes32[] memory storageSlots) internal view returns (bytes32[] memory) {
uint256 slotsLength = storageSlots.length;
bytes32[] memory values = new bytes32[](slotsLength);
for (uint256 i = 0; i < slotsLength; i++) {
bytes32 slotValue = _getValueBySlot(storageSlots[i]);
values[i] = slotValue;
}
return values;
}
function _setAddressBySlot(bytes32 _slot, address _address) internal {
assembly {
sstore(_slot, _address)
}
}
function _getAddressBySlot(bytes32 _slot) internal view returns (address _address) {
assembly {
_address := sload(_slot)
}
}
function _getValueBySlot(bytes32 _slot) internal view returns (bytes32 _value) {
assembly {
_value := sload(_slot)
}
}
}
文件 10 的 33:IBeforeTransfer.sol
pragma solidity ^0.8.0;
interface IBeforeTransfer {
function beforeTransfer(address from, address to, uint256 poolId) external;
}
文件 11 的 33:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 12 的 33:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 13 的 33:IERC2981.sol
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
interface IERC2981 is IERC165 {
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}
文件 14 的 33:IERC4906.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
import "./IERC721.sol";
interface IERC4906 is IERC165, IERC721 {
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
文件 15 的 33:IERC721.sol
pragma solidity ^0.8.0;
import "../../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 的 33:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../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 的 33:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../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 的 33:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 19 的 33:IFirewall.sol
pragma solidity ^0.8;
interface IFirewall {
function preExecution(address sender, bytes memory data, uint256 value) external;
function postExecution(address sender, bytes memory data, uint256 value) external;
function preExecutionPrivateInvariants(address sender, bytes memory data, uint256 value) external returns (bytes32[] calldata);
function postExecutionPrivateInvariants(
address sender,
bytes memory data,
uint256 value,
bytes32[] calldata preValues,
bytes32[] calldata postValues
) external;
}
文件 20 的 33:IFirewallConsumer.sol
pragma solidity ^0.8;
interface IFirewallConsumer {
function firewallAdmin() external returns (address);
}
文件 21 的 33:IInnerWithdraw.sol
pragma solidity ^0.8.0;
interface IInnerWithdraw {
function getInnerIdsArray(uint256 poolId) external returns (uint256[] calldata ids);
}
文件 22 的 33:ILockDealNFT.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "./IProvider.sol";
import "./IVaultManager.sol";
interface ILockDealNFT is IERC721Enumerable {
function approvedContracts(address contractAddress) external view returns (bool);
function mintAndTransfer(
address owner,
address token,
uint256 amount,
IProvider provider
) external returns (uint256 poolId);
function safeMintAndTransfer(
address owner,
address token,
address from,
uint256 amount,
IProvider provider,
bytes calldata data
) external returns (uint256 poolId);
function cloneVaultId(uint256 destinationPoolId, uint256 sourcePoolId) external;
function mintForProvider(address owner, IProvider provider) external returns (uint256 poolId);
function getData(uint256 poolId) external view returns (BasePoolInfo memory poolInfo);
function getFullData(uint256 poolId) external view returns (BasePoolInfo[] memory poolInfo);
function tokenOf(uint256 poolId) external view returns (address token);
function vaultManager() external view returns (IVaultManager);
function poolIdToProvider(uint256 poolId) external view returns (IProvider provider);
function getWithdrawableAmount(uint256 poolId) external view returns (uint256 withdrawalAmount);
struct BasePoolInfo {
IProvider provider;
string name;
uint256 poolId;
uint256 vaultId;
address owner;
address token;
uint256[] params;
}
}
文件 23 的 33:ILockDealNFTEvents.sol
pragma solidity ^0.8.0;
import "@poolzfinance/poolz-helper-v2/contracts/interfaces/IProvider.sol";
interface ILockDealNFTEvents {
event ContractApproved(address indexed contractAddress, bool status);
event BaseURIChanged(string oldBaseURI, string newBaseURI);
event TokenWithdrawn(uint256 poolId, address indexed owner, uint256 withdrawnAmount, uint256 leftAmount);
event PoolSplit(
uint256 poolId,
address indexed owner,
uint256 newPoolId,
address indexed newOwner,
uint256 splitLeftAmount,
uint256 newSplitLeftAmount
);
}
文件 24 的 33:IProvider.sol
pragma solidity ^0.8.0;
interface IProvider {
event UpdateParams(uint256 indexed poolId, uint256[] params);
function withdraw(uint256 tokenId) external returns (uint256 withdrawnAmount, bool isFinal);
function split(uint256 oldPoolId, uint256 newPoolId, uint256 ratio) external;
function registerPool(uint256 poolId, uint256[] calldata params) external;
function getParams(uint256 poolId) external view returns (uint256[] memory params);
function getWithdrawableAmount(uint256 poolId) external view returns (uint256 withdrawalAmount);
function currentParamsTargetLength() external view returns (uint256);
function name() external view returns (string memory);
function getSubProvidersPoolIds(uint256 poolID) external view returns (uint256[] memory poolIds);
}
文件 25 的 33:IVaultManager.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
interface IVaultManager is IERC2981 {
function depositByToken(address _tokenAddress, uint _amount) external returns (uint vaultId);
function safeDeposit(
address _tokenAddress,
uint _amount,
address _from,
bytes memory _signature
) external returns (uint vaultId);
function withdrawByVaultId(uint _vaultId, address to, uint _amount) external;
function vaultIdToTokenAddress(uint _vaultId) external view returns (address token);
function vaultIdToTradeStartTime(uint256 _vaultId) external view returns (uint256 startTime);
}
文件 26 的 33:LockDealNFT.sol
pragma solidity ^0.8.0;
import "./LockDealNFTInternal.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract LockDealNFT is LockDealNFTInternal, IERC721Receiver {
constructor(address _vaultManager, string memory _baseURI) ERC721("LockDealNFT", "LDNFT") {
_notZeroAddress(_vaultManager);
vaultManager = IVaultManager(_vaultManager);
approvedContracts[address(this)] = true;
baseURI = _baseURI;
}
function mintForProvider(
address owner,
IProvider provider
) external firewallProtected onlyApprovedContract(address(provider)) notZeroAddress(owner) returns (uint256 poolId) {
poolId = _mint(owner, provider);
}
function mintAndTransfer(
address owner,
address token,
uint256 amount,
IProvider provider
)
external
firewallProtected
onlyApprovedContract(address(provider))
notZeroAddress(owner)
notZeroAddress(token)
notZeroAmount(amount)
returns (uint256 poolId)
{
poolId = _mint(owner, provider);
IERC20(token).approve(address(vaultManager), amount);
poolIdToVaultId[poolId] = vaultManager.depositByToken(token, amount);
}
function safeMintAndTransfer(
address owner,
address token,
address from,
uint256 amount,
IProvider provider,
bytes calldata data
)
external
firewallProtected
onlyApprovedContract(address(provider))
notZeroAddress(owner)
notZeroAddress(token)
notZeroAmount(amount)
returns (uint256 poolId)
{
poolId = _mint(owner, provider);
poolIdToVaultId[poolId] = vaultManager.safeDeposit(token, amount, from, data);
}
function cloneVaultId(
uint256 destinationPoolId,
uint256 sourcePoolId
) external firewallProtected onlyApprovedContract(msg.sender) validPoolId(destinationPoolId) validPoolId(sourcePoolId) {
poolIdToVaultId[destinationPoolId] = poolIdToVaultId[sourcePoolId];
}
function setApprovedContract(address contractAddress, bool status) external onlyOwner onlyContract(contractAddress) {
approvedContracts[contractAddress] = status;
emit ContractApproved(contractAddress, status);
}
function approvePoolTransfers(bool status) external {
require(approvedPoolUserTransfers[msg.sender] != status, "status is the same as before");
approvedPoolUserTransfers[msg.sender] = status;
}
function onERC721Received(
address,
address from,
uint256 poolId,
bytes calldata data
) external override firewallProtected returns (bytes4) {
require(msg.sender == address(this), "invalid nft contract");
_handleReturn(poolId, from, data.length > 0 ? _split(poolId, from, data) : _withdraw(from, poolId));
return IERC721Receiver.onERC721Received.selector;
}
function updateAllMetadata() external onlyOwner {
emit MetadataUpdate(type(uint256).max);
}
function transferFrom(address from, address to, uint256 tokenId) public override(ERC721, IERC721) {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, "");
}
function setBaseURI(string memory newBaseURI) external onlyOwner {
require(
keccak256(abi.encodePacked(baseURI)) != keccak256(abi.encodePacked(newBaseURI)),
"can't set the same baseURI"
);
string memory oldBaseURI = baseURI;
baseURI = newBaseURI;
emit BaseURIChanged(oldBaseURI, newBaseURI);
}
}
文件 27 的 33:LockDealNFTInternal.sol
pragma solidity ^0.8.0;
import "./LockDealNFTModifiers.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@poolzfinance/poolz-helper-v2/contracts/interfaces/IBeforeTransfer.sol";
import "@poolzfinance/poolz-helper-v2/contracts/interfaces/IInnerWithdraw.sol";
import "@ironblocks/firewall-consumer/contracts/FirewallConsumer.sol";
abstract contract LockDealNFTInternal is LockDealNFTModifiers, FirewallConsumer {
function _transfer(address from, address to, uint256 poolId)
internal
override
firewallProtectedSig(0x30e0789e)
{
if (
from != address(0) &&
ERC165Checker.supportsInterface(address(poolIdToProvider[poolId]), type(IBeforeTransfer).interfaceId)
) {
IBeforeTransfer(address(poolIdToProvider[poolId])).beforeTransfer(from, to, poolId);
}
if (!(approvedContracts[to] || approvedContracts[from])) {
require(approvedPoolUserTransfers[from], "Pool transfer not approved by user");
require(
vaultManager.vaultIdToTradeStartTime(poolIdToVaultId[poolId]) < block.timestamp,
"Can't transfer before trade start time"
);
}
super._transfer(from, to, poolId);
}
function _mint(address owner, IProvider provider)
internal
firewallProtectedSig(0x3c99ae44)
returns (uint256 newPoolId)
{
newPoolId = totalSupply();
_safeMint(owner, newPoolId);
poolIdToProvider[newPoolId] = provider;
}
function _parseData(bytes calldata data, address from) internal pure returns (uint256 ratio, address newOwner) {
(ratio, newOwner) = data.length == 32
? (abi.decode(data, (uint256)), from)
: abi.decode(data, (uint256, address));
}
function _baseURI() internal view override returns (string memory) {
return baseURI;
}
function _handleReturn(uint256 poolId, address from, bool isFinal)
internal
firewallProtectedSig(0x1d50d0db)
{
if (!isFinal) {
_transfer(address(this), from, poolId);
}
}
function _withdrawFromVault(uint256 poolId, uint256 withdrawnAmount, address from)
internal
firewallProtectedSig(0x05d6a92f)
{
if (withdrawnAmount > 0) {
vaultManager.withdrawByVaultId(poolIdToVaultId[poolId], from, withdrawnAmount);
emit MetadataUpdate(poolId);
emit TokenWithdrawn(poolId, from, withdrawnAmount, _getData(poolId).params[0]);
}
}
function _withdraw(address from, uint256 poolId)
internal
firewallProtectedSig(0xb790a77b)
returns (bool isFinal)
{
uint256 withdrawnAmount;
IProvider provider = poolIdToProvider[poolId];
(withdrawnAmount, isFinal) = provider.withdraw(poolId);
if (ERC165Checker.supportsInterface(address(provider), type(IInnerWithdraw).interfaceId)) {
withdrawnAmount = 0;
uint256[] memory ids = IInnerWithdraw(address(provider)).getInnerIdsArray(poolId);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
require(ownerOf(id) == address(poolIdToProvider[poolId]), "invalid inner id");
_withdraw(from, id);
}
}
_withdrawFromVault(poolId, withdrawnAmount, from);
}
function _split(uint256 poolId, address from, bytes calldata data)
internal
firewallProtectedSig(0x1746b892)
returns (bool isFinal)
{
(uint256 ratio, address newOwner) = _parseData(data, from);
isFinal = _split(poolId, from, ratio, newOwner);
}
struct SplitLocals {
IProvider provider;
uint256 newPoolId;
}
function _split(
uint256 poolId,
address from,
uint256 ratio,
address newOwner
)
private
notZeroAddress(newOwner)
notZeroAmount(ratio)
returns (bool isFinal)
{
require(ratio <= 1e21, "split amount exceeded");
SplitLocals memory locals;
locals.provider = poolIdToProvider[poolId];
locals.newPoolId = _mint(newOwner, locals.provider);
poolIdToVaultId[locals.newPoolId] = poolIdToVaultId[poolId];
locals.provider.split(poolId, locals.newPoolId, ratio);
isFinal = locals.provider.getParams(poolId)[0] == 0;
uint256 splitLeftAmount = _getData(poolId).params[0];
emit PoolSplit(poolId, from, locals.newPoolId, newOwner, splitLeftAmount, _getData(locals.newPoolId).params[0]);
emit MetadataUpdate(poolId);
}
}
文件 28 的 33:LockDealNFTModifiers.sol
pragma solidity ^0.8.0;
import "./LockDealNFTState.sol";
abstract contract LockDealNFTModifiers is LockDealNFTState {
modifier onlyApprovedContract(address contractAddress) {
_onlyApprovedContract(contractAddress);
if (contractAddress != msg.sender) {
_onlyApprovedContract(msg.sender);
}
_;
}
modifier onlyContract(address contractAddress) {
_onlyContract(contractAddress);
_;
}
modifier notZeroAddress(address _address) {
_notZeroAddress(_address);
_;
}
modifier notZeroAmount(uint256 amount) {
_notZeroAmount(amount);
_;
}
modifier validPoolId(uint256 poolId) {
_validPoolId(poolId);
_;
}
function _notZeroAddress(address _address) internal pure {
require(_address != address(0x0), "Zero Address is not allowed");
}
function _onlyContract(address contractAddress) private view {
require(Address.isContract(contractAddress), "Invalid contract address");
}
function _onlyApprovedContract(address contractAddress) internal view {
require(approvedContracts[contractAddress], "Contract not approved");
}
function _notZeroAmount(uint256 amount) private pure {
require(amount > 0, "amount must be greater than 0");
}
function _validPoolId(uint256 poolId) internal view {
require(_exists(poolId), "Pool does not exist");
}
}
文件 29 的 33:LockDealNFTState.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/interfaces/IERC4906.sol";
import "@poolzfinance/poolz-helper-v2/contracts/interfaces/IVaultManager.sol";
import "@poolzfinance/poolz-helper-v2/contracts/interfaces/ILockDealNFT.sol";
import "@poolzfinance/poolz-helper-v2/contracts/Array.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./ILockDealNFTEvents.sol";
abstract contract LockDealNFTState is ERC721Enumerable, ILockDealNFTEvents, Ownable, IERC4906, ILockDealNFT, IERC2981 {
string public baseURI;
IVaultManager public vaultManager;
mapping(uint256 => IProvider) public poolIdToProvider;
mapping(uint256 => uint256) public poolIdToVaultId;
mapping(address => bool) public approvedPoolUserTransfers;
mapping(address => bool) public approvedContracts;
function getData(uint256 poolId) public view returns (BasePoolInfo memory poolInfo) {
if (_exists(poolId)) {
poolInfo = _getData(poolId);
}
}
function getFullData(uint256 poolId) public view returns (BasePoolInfo[] memory poolInfo) {
if (_exists(poolId)) {
uint256[] memory poolIds = poolIdToProvider[poolId].getSubProvidersPoolIds(poolId);
uint256 length = poolIds.length + 1;
poolInfo = new BasePoolInfo[](length);
poolInfo[0] = _getData(poolId);
for (uint256 i = 1; i < length; ++i) {
poolInfo[i] = _getData(poolIds[i - 1]);
}
}
}
function _getData(uint256 poolId) internal view returns (BasePoolInfo memory poolInfo) {
IProvider provider = poolIdToProvider[poolId];
poolInfo = BasePoolInfo(
provider,
provider.name(),
poolId,
poolIdToVaultId[poolId],
ownerOf(poolId),
tokenOf(poolId),
provider.getParams(poolId)
);
}
function getUserDataByTokens(
address user,
address[] calldata tokens,
uint256 from,
uint256 to
) public view returns (BasePoolInfo[] memory userPoolInfo) {
require(from <= to, "Invalid range");
require(to < balanceOf(user, tokens), "Range greater than user pool count");
userPoolInfo = new BasePoolInfo[](to - from + 1);
uint256 userPoolIndex = 0;
for (uint256 i = from; i <= to; ++i) {
uint256 poolId = tokenOfOwnerByIndex(user, tokens, i);
userPoolInfo[userPoolIndex++] = getData(poolId);
}
}
function tokenOf(uint256 poolId) public view returns (address token) {
token = vaultManager.vaultIdToTokenAddress(poolIdToVaultId[poolId]);
}
function getWithdrawableAmount(uint256 poolId) external view returns (uint256 withdrawalAmount) {
if (_exists(poolId)) {
withdrawalAmount = poolIdToProvider[poolId].getWithdrawableAmount(poolId);
}
}
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view override returns (address receiver, uint256 royaltyAmount) {
(receiver, royaltyAmount) = vaultManager.royaltyInfo(poolIdToVaultId[tokenId], salePrice);
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC721Enumerable, IERC165) returns (bool) {
return
interfaceId == type(IERC2981).interfaceId ||
interfaceId == type(ILockDealNFT).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner, address[] calldata tokens) public view returns (uint256 balance) {
uint256 fullBalanceOf = balanceOf(owner);
for (uint256 i = 0; i < fullBalanceOf; ++i) {
if (Array.isInArray(tokens, tokenOf(tokenOfOwnerByIndex(owner, i)))) {
++balance;
}
}
}
function tokenOfOwnerByIndex(
address owner,
address[] calldata tokens,
uint256 index
) public view returns (uint256 poolId) {
uint256 length = balanceOf(owner, tokens);
require(index < length, "invalid poolId index by token association");
uint256 fullBalanceOf = balanceOf(owner);
uint256 j = 0;
for (uint256 i = 0; i < fullBalanceOf; ++i) {
poolId = tokenOfOwnerByIndex(owner, i);
if (Array.isInArray(tokens, tokenOf(poolId)) && j++ == index) {
return poolId;
}
}
}
}
文件 30 的 33:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
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) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
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 (rounding == Rounding.Up && 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 + (rounding == Rounding.Up && 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 + (rounding == Rounding.Up && 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 + (rounding == Rounding.Up && 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 31 的 33:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 32 的 33:SignedMath.sol
pragma solidity ^0.8.0;
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);
}
}
}
文件 33 的 33:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
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), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(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) {
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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
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 keccak256(bytes(a)) == keccak256(bytes(b));
}
}
{
"compilationTarget": {
"contracts/LockDealNFT/contracts/LockDealNFT/LockDealNFT.sol": "LockDealNFT"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_vaultManager","type":"address"},{"internalType":"string","name":"_baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oldBaseURI","type":"string"},{"indexed":false,"internalType":"string","name":"newBaseURI","type":"string"}],"name":"BaseURIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"ContractApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"FirewallAdminUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newFirewall","type":"address"}],"name":"FirewallUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","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":"uint256","name":"poolId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPoolId","type":"uint256"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"splitLeftAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSplitLeftAmount","type":"uint256"}],"name":"PoolSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leftAmount","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptFirewallAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"approvePoolTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedContracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedPoolUserTransfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"destinationPoolId","type":"uint256"},{"internalType":"uint256","name":"sourcePoolId","type":"uint256"}],"name":"cloneVaultId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"firewallAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"name":"getData","outputs":[{"components":[{"internalType":"contract IProvider","name":"provider","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"params","type":"uint256[]"}],"internalType":"struct ILockDealNFT.BasePoolInfo","name":"poolInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"name":"getFullData","outputs":[{"components":[{"internalType":"contract IProvider","name":"provider","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"params","type":"uint256[]"}],"internalType":"struct ILockDealNFT.BasePoolInfo[]","name":"poolInfo","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"getUserDataByTokens","outputs":[{"components":[{"internalType":"contract IProvider","name":"provider","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"params","type":"uint256[]"}],"internalType":"struct ILockDealNFT.BasePoolInfo[]","name":"userPoolInfo","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"name":"getWithdrawableAmount","outputs":[{"internalType":"uint256","name":"withdrawalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"contract IProvider","name":"provider","type":"address"}],"name":"mintAndTransfer","outputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract IProvider","name":"provider","type":"address"}],"name":"mintForProvider","outputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToProvider","outputs":[{"internalType":"contract IProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToVaultId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"targetPayload","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeFunctionCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"contract IProvider","name":"provider","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeMintAndTransfer","outputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setApprovedContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setApprovedTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_firewall","type":"address"}],"name":"setFirewall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_firewallAdmin","type":"address"}],"name":"setFirewallAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"name":"tokenOf","outputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"poolId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAllMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultManager","outputs":[{"internalType":"contract IVaultManager","name":"","type":"address"}],"stateMutability":"view","type":"function"}]