编译器
0.8.20+commit.a1b79de6
文件 1 的 15:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 2 的 15:ERC165Checker.sol
pragma solidity ^0.8.20;
import {IERC165} from "./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.encodeCall(IERC165.supportsInterface, (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;
}
}
文件 3 的 15:ICurve.sol
pragma solidity >=0.8.20;
interface ICurve {
function curveMath(uint256 base, uint256 add) external pure returns (uint256);
}
文件 4 的 15:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 5 的 15:IERC20.sol
pragma solidity ^0.8.20;
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 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 6 的 15:IERC20Permit.sol
pragma solidity ^0.8.20;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 7 的 15: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);
}
文件 8 的 15:IFoundry.sol
pragma solidity >=0.8.20;
interface IFoundry {
struct App {
string name;
address owner;
address operator;
address publicNFT;
address mortgageNFT;
address market;
address payToken;
}
event CreateApp(
uint256 appId,
string name,
address owner,
address operator,
address curve,
address payToken,
uint256 buyFee,
uint256 sellFee,
address publicNFT,
address mortgageNFT,
address market,
address sender
);
event CreateToken(
uint256 appId,
string tid,
bytes tData,
uint256[] nftTokenIds,
uint256[] nftPercents,
address[] nftOwners,
bytes[] nftData,
address sender
);
event SetAppOwner(uint256 appId, address newOwner, address sender);
event SetMortgageFee(uint256 appId, uint256 newMortgageFee, address sender);
event SetMortgageFeeRecipient(uint256 appId, address newMortgageFeeOwner, address sender);
function FEE_DENOMINATOR() external view returns (uint256);
function TOTAL_PERCENT() external view returns (uint256);
function publicNFTFactory() external view returns (address);
function mortgageNFTFactory() external view returns (address);
function marketFactory() external view returns (address);
function nextAppId() external view returns (uint256);
function defaultMortgageFee() external view returns (uint256);
function defaultMortgageFeeRecipient() external view returns (address);
function mortgageFee(uint256 appId) external view returns (uint256);
function mortgageFeeRecipient(uint256 appId) external view returns (address);
function apps(uint256 appId) external view returns (App memory app);
function tokenExist(uint256 appId, string memory tid) external view returns (bool);
function tokenData(uint256 appId, string memory tid) external view returns (bytes memory);
function createApp(
string memory name,
address owner,
address operator,
address curve,
address payToken,
uint256 buyFee,
uint256 sellFee
) external;
function createToken(
uint256 appId,
string memory tid,
bytes memory tData,
uint256[] memory nftPercents,
address[] memory nftOwners,
bytes[] memory nftData
) external returns (uint256[] memory tokenIds);
function setAppOwner(uint256 appId, address newOwner) external;
function setMortgageFee(uint256 appId, uint256 newMortgageFee) external;
function setMortgageFeeRecipient(uint256 appId, address newMortgageFeeRecipient) external;
}
文件 9 的 15:IMarket.sol
pragma solidity >=0.8.20;
interface IMarket {
event Initialize(address publicNFT, address mortgageNFT);
event Buy(
string tid,
uint256 tokenAmount,
uint256 payTokenAmount,
address sender,
address user,
uint256[] feeTokenIds,
address[] feeOwners,
uint256[] feeAmounts
);
event Sell(
string tid,
uint256 tokenAmount,
uint256 payTokenAmount,
address sender,
address user,
uint256[] feeTokenIds,
address[] feeOwners,
uint256[] feeAmounts
);
event Mortgage(
uint256 tokenId,
string tid,
uint256 tokenAmount,
uint256 payTokenAmount,
uint256 feeAmount,
address sender
);
event Redeem(uint256 tokenId, string tid, uint256 tokenAmount, uint256 payTokenAmount, address sender);
event Multiply(
uint256 tokenId,
string tid,
uint256 multiplyAmount,
uint256 payTokenAmount,
uint256 feeAmount,
address sender,
uint256[] feeTokenIds,
address[] feeOwners,
uint256[] feeAmounts
);
event Cash(
uint256 tokenId,
string tid,
uint256 tokenAmount,
uint256 payTokenAmount,
address sender,
uint256[] feeTokenIds,
address[] feeOwners,
uint256[] feeAmounts
);
event Merge(
uint256 tokenId,
string tid,
uint256 otherTokenId,
uint256 payTokenAmount,
uint256 feeAmount,
address sender
);
event Split(
uint256 tokenId,
uint256 newTokenId,
string tid,
uint256 splitAmount,
uint256 payTokenAmount,
address sender
);
function feeDenominator() external view returns (uint256);
function totalPercent() external view returns (uint256);
function foundry() external view returns (address);
function appId() external view returns (uint256);
function curve() external view returns (address);
function payToken() external view returns (address);
function buyFee() external view returns (uint256);
function sellFee() external view returns (uint256);
function publicNFT() external view returns (address);
function mortgageNFT() external view returns (address);
function initialize(address publicNFT, address mortgageNFT) external;
function totalSupply(string memory tid) external view returns (uint256);
function balanceOf(string memory tid, address account) external view returns (uint256);
function getBuyPayTokenAmount(string memory tid, uint256 tokenAmount) external view returns (uint256 payTokenAmount);
function getSellPayTokenAmount(string memory tid, uint256 tokenAmount) external view returns (uint256 payTokenAmount);
function getPayTokenAmount(uint256 base, uint256 add) external view returns (uint256 payTokenAmount);
function buy(string memory tid, uint256 tokenAmount) external payable returns (uint256 payTokenAmount);
function buyProxy(
string memory tid,
uint256 tokenAmount,
address user
) external payable returns (uint256 payTokenAmount);
function sell(string memory tid, uint256 tokenAmount) external returns (uint256 payTokenAmount);
function sellProxy(string memory tid, uint256 tokenAmount, address user) external returns (uint256 payTokenAmount);
function mortgage(
string memory tid,
uint256 tokenAmount
) external returns (uint256 nftTokenId, uint256 payTokenAmount);
function mortgageProxy(
string memory tid,
uint256 tokenAmount,
address user
) external returns (uint256 nftTokenId, uint256 payTokenAmount);
function mortgageAdd(uint256 nftTokenId, uint256 tokenAmount) external returns (uint256 payTokenAmount);
function mortgageAddProxy(uint256 nftTokenId, uint256 tokenAmount) external returns (uint256 payTokenAmount);
function redeem(uint256 nftTokenId, uint256 tokenAmount) external payable returns (uint256 payTokenAmount);
function redeemProxy(uint256 nftTokenId, uint256 tokenAmount) external payable returns (uint256 payTokenAmount);
function multiply(
string memory tid,
uint256 multiplyAmount
) external payable returns (uint256 nftTokenId, uint256 payTokenAmount);
function multiplyProxy(
string memory tid,
uint256 multiplyAmount,
address user
) external payable returns (uint256 nftTokenId, uint256 payTokenAmount);
function multiplyAdd(uint256 nftTokenId, uint256 multiplyAmount) external payable returns (uint256 payTokenAmount);
function multiplyAddProxy(
uint256 nftTokenId,
uint256 multiplyAmount
) external payable returns (uint256 payTokenAmount);
function cash(uint256 nftTokenId, uint256 tokenAmount) external returns (uint256 payTokenAmount);
function cashProxy(uint256 nftTokenId, uint256 tokenAmount) external returns (uint256 payTokenAmount);
function merge(uint256 nftTokenId, uint256 otherNFTTokenId) external returns (uint256 payTokenAmount);
function mergeProxy(uint256 nftTokenId, uint256 otherNFTTokenId) external returns (uint256 payTokenAmount);
function split(
uint256 nftTokenId,
uint256 splitAmount
) external payable returns (uint256 payTokenAmount, uint256 newNFTTokenId);
function splitProxy(
uint256 nftTokenId,
uint256 splitAmount
) external payable returns (uint256 payTokenAmount, uint256 newNFTTokenId);
}
文件 10 的 15:IMortgageNFT.sol
pragma solidity >=0.8.20;
interface IMortgageNFT {
struct Info {
string tid;
uint256 tokenId;
uint256 amount;
}
event Initialize(address market);
event Mint(address to, string tid, uint256 amount);
event Burn(uint256 tokenId);
event Add(uint256 tokenId, uint256 amount);
event Remove(uint256 tokenId, uint256 amount);
event SetMortgageNFTView(address newMortgageNFTView, address sender);
function foundry() external view returns (address);
function appId() external view returns (uint256);
function market() external view returns (address);
function mortgageNFTView() external view returns (address);
function info(uint256 tokenId) external view returns (string memory tid, uint256 amount);
function initialize(address market) external;
function isApprovedOrOwner(address addr, uint256 tokenId) external view returns (bool);
function mint(address to, string memory tid, uint256 amount) external returns (uint256 tokenId);
function burn(uint256 tokenId) external;
function add(uint256 tokenId, uint256 amount) external;
function remove(uint256 tokenId, uint256 amount) external;
function setMortgageNFTView(address newMortgageNFTView) external;
function tokenInfosOfOwner(address owner) external view returns (IMortgageNFT.Info[] memory infos);
function tokenInfosOfOwnerByTid(
address owner,
string memory tid
) external view returns (IMortgageNFT.Info[] memory infos);
}
文件 11 的 15:IPublicNFT.sol
pragma solidity >=0.8.20;
interface IPublicNFT {
struct Info {
string tid;
uint256 percent;
bytes data;
}
event Mint(string tid, uint256[] tokenIds, uint256[] percents, address[] owners, bytes[] data);
event SetPublicNFTView(address newPublicNFTView, address sender);
function foundry() external view returns (address);
function appId() external view returns (uint256);
function publicNFTView() external view returns (address);
function tokenIdToInfo(
uint256 tokenId
) external view returns (string memory tid, uint256 percent, bytes memory data, address owner);
function tidToTokenIds(string memory tid) external view returns (uint256[] memory);
function tidToInfos(
string memory tid
)
external
view
returns (uint256[] memory tokenIds, uint256[] memory percents, bytes[] memory data, address[] memory owners);
function mint(
string memory tid,
uint256[] memory percents,
address[] memory owners,
bytes[] memory data
) external returns (uint256[] memory tokenIds);
function setPublicNFTView(address newPublicNFTView) external;
}
文件 12 的 15:IPublicNFTVault.sol
pragma solidity >=0.8.20;
interface IPublicNFTVault {
function recordReceiveBuySellFee(uint256 tokenId, uint256 amount) external returns (bool);
}
文件 13 的 15:Market.sol
pragma solidity >=0.8.20;
import "./interfaces/IPublicNFT.sol";
import "./interfaces/IMortgageNFT.sol";
import "./interfaces/IMarket.sol";
import "./interfaces/IFoundry.sol";
import "./interfaces/ICurve.sol";
import "./interfaces/IPublicNFTVault.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
contract Market is IMarket, ReentrancyGuard {
uint256 public immutable override feeDenominator;
uint256 public immutable override totalPercent;
address public immutable override foundry;
uint256 public immutable override appId;
address public immutable override curve;
address public immutable override payToken;
uint256 public immutable override buyFee;
uint256 public immutable override sellFee;
address public override publicNFT;
address public override mortgageNFT;
mapping(string => uint256) private _totalSupply;
mapping(string => mapping(address => uint256)) private _balanceOf;
modifier onlyAppOperator() {
require(msg.sender == IFoundry(foundry).apps(appId).operator, "onlyAppOperator");
_;
}
constructor(
address _foundry,
uint256 _appId,
uint256 _feeDenominator,
uint256 _totalPercent,
address _curve,
address _payToken,
uint256 _buyFee,
uint256 _sellFee
) {
foundry = _foundry;
appId = _appId;
feeDenominator = _feeDenominator;
totalPercent = _totalPercent;
curve = _curve;
payToken = _payToken;
buyFee = _buyFee;
sellFee = _sellFee;
}
function initialize(address _publicNFT, address _mortgageNFT) external override {
require(msg.sender == foundry, "onlyFoundry");
publicNFT = _publicNFT;
mortgageNFT = _mortgageNFT;
emit Initialize(_publicNFT, _mortgageNFT);
}
function totalSupply(string memory tid) external view override returns (uint256) {
return _totalSupply[tid];
}
function balanceOf(string memory tid, address account) external view override returns (uint256) {
return _balanceOf[tid][account];
}
function getBuyPayTokenAmount(
string memory tid,
uint256 tokenAmount
) public view override returns (uint256 payTokenAmount) {
uint256 ts = _totalSupply[tid];
return getPayTokenAmount(ts, tokenAmount);
}
function getSellPayTokenAmount(
string memory tid,
uint256 tokenAmount
) public view override returns (uint256 payTokenAmount) {
uint256 ts = _totalSupply[tid];
return getPayTokenAmount(ts - tokenAmount, tokenAmount);
}
function getPayTokenAmount(uint256 base, uint256 add) public view override returns (uint256 payTokenAmount) {
return ICurve(curve).curveMath(base, add);
}
function buy(
string memory tid,
uint256 tokenAmount
) external payable override nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _buy(tid, tokenAmount, msg.sender);
}
function buyProxy(
string memory tid,
uint256 tokenAmount,
address user
) external payable override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _buy(tid, tokenAmount, user);
}
function sell(
string memory tid,
uint256 tokenAmount
) external override nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _sell(tid, tokenAmount, msg.sender);
}
function sellProxy(
string memory tid,
uint256 tokenAmount,
address user
) external override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _sell(tid, tokenAmount, user);
}
function mortgage(
string memory tid,
uint256 tokenAmount
) external override nonReentrant returns (uint256 nftTokenId, uint256 payTokenAmount) {
(nftTokenId, payTokenAmount) = _mortgage(tid, tokenAmount, msg.sender);
}
function mortgageProxy(
string memory tid,
uint256 tokenAmount,
address user
) external override onlyAppOperator nonReentrant returns (uint256 nftTokenId, uint256 payTokenAmount) {
(nftTokenId, payTokenAmount) = _mortgage(tid, tokenAmount, user);
}
function mortgageAdd(
uint256 nftTokenId,
uint256 tokenAmount
) external override nonReentrant returns (uint256 payTokenAmount) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE");
payTokenAmount = _mortgageAdd(nftTokenId, tokenAmount);
}
function mortgageAddProxy(
uint256 nftTokenId,
uint256 tokenAmount
) external override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _mortgageAdd(nftTokenId, tokenAmount);
}
function redeem(
uint256 nftTokenId,
uint256 tokenAmount
) external payable override nonReentrant returns (uint256 payTokenAmount) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE");
payTokenAmount = _redeem(nftTokenId, tokenAmount);
}
function redeemProxy(
uint256 nftTokenId,
uint256 tokenAmount
) external payable override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _redeem(nftTokenId, tokenAmount);
}
function multiply(
string memory tid,
uint256 multiplyAmount
) external payable override nonReentrant returns (uint256 nftTokenId, uint256 payTokenAmount) {
(nftTokenId, payTokenAmount) = _multiply(tid, multiplyAmount, msg.sender);
}
function multiplyProxy(
string memory tid,
uint256 multiplyAmount,
address user
) external payable override onlyAppOperator nonReentrant returns (uint256 nftTokenId, uint256 payTokenAmount) {
(nftTokenId, payTokenAmount) = _multiply(tid, multiplyAmount, user);
}
function multiplyAdd(
uint256 nftTokenId,
uint256 multiplyAmount
) external payable override nonReentrant returns (uint256 payTokenAmount) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE");
payTokenAmount = _multiplyAdd(nftTokenId, multiplyAmount);
}
function multiplyAddProxy(
uint256 nftTokenId,
uint256 multiplyAmount
) external payable override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _multiplyAdd(nftTokenId, multiplyAmount);
}
function cash(
uint256 nftTokenId,
uint256 tokenAmount
) external override nonReentrant returns (uint256 payTokenAmount) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE");
payTokenAmount = _cash(nftTokenId, tokenAmount);
}
function cashProxy(
uint256 nftTokenId,
uint256 tokenAmount
) external override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _cash(nftTokenId, tokenAmount);
}
function merge(
uint256 nftTokenId,
uint256 otherNFTTokenId
) external override nonReentrant returns (uint256 payTokenAmount) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE1");
require(IERC721(mortgageNFT).ownerOf(otherNFTTokenId) == msg.sender, "AOE2");
payTokenAmount = _merge(nftTokenId, otherNFTTokenId);
}
function mergeProxy(
uint256 nftTokenId,
uint256 otherNFTTokenId
) external override onlyAppOperator nonReentrant returns (uint256 payTokenAmount) {
payTokenAmount = _merge(nftTokenId, otherNFTTokenId);
}
function split(
uint256 nftTokenId,
uint256 splitAmount
) external payable override nonReentrant returns (uint256 payTokenAmount, uint256 newNFTTokenId) {
require(IERC721(mortgageNFT).ownerOf(nftTokenId) == msg.sender, "AOE");
(payTokenAmount, newNFTTokenId) = _split(nftTokenId, splitAmount);
}
function splitProxy(
uint256 nftTokenId,
uint256 splitAmount
) external payable override onlyAppOperator nonReentrant returns (uint256 payTokenAmount, uint256 newNFTTokenId) {
(payTokenAmount, newNFTTokenId) = _split(nftTokenId, splitAmount);
}
function _buy(string memory tid, uint256 tokenAmount, address user) private returns (uint256 payTokenAmount) {
require(IFoundry(foundry).tokenExist(appId, tid), "TE");
require(tokenAmount > 0, "TAE");
uint256[] memory feeTokenIds;
address[] memory feeTos;
uint256[] memory feeAmounts;
(payTokenAmount, feeTokenIds, feeTos, feeAmounts) = _buyWithoutPay(user, tid, tokenAmount);
if (_payTokenIsERC20()) {
_transferFromERC20PayTokenFromSender(payTokenAmount);
_batchTransferERC20PayTokenToNFTOwners(feeTokenIds, feeTos, feeAmounts);
} else {
require(msg.value >= payTokenAmount, "VE");
_batchTransferEthToNFTOwners(feeTokenIds, feeTos, feeAmounts);
_refundETH(payTokenAmount);
}
emit Buy(tid, tokenAmount, payTokenAmount, msg.sender, user, feeTokenIds, feeTos, feeAmounts);
}
function _sell(string memory tid, uint256 tokenAmount, address user) private returns (uint256 payTokenAmount) {
require(IFoundry(foundry).tokenExist(appId, tid), "TE");
require(tokenAmount > 0, "TAE");
require(tokenAmount <= _balanceOf[tid][user], "TAE");
uint256[] memory feeTokenIds;
address[] memory feeTos;
uint256[] memory feeAmounts;
(payTokenAmount, feeTokenIds, feeTos, feeAmounts) = _sellWithoutPay(user, tid, tokenAmount);
if (_payTokenIsERC20()) {
_transferERC20PayToken(msg.sender, payTokenAmount);
_batchTransferERC20PayTokenToNFTOwners(feeTokenIds, feeTos, feeAmounts);
} else {
_transferEth(msg.sender, payTokenAmount);
_batchTransferEthToNFTOwners(feeTokenIds, feeTos, feeAmounts);
}
emit Sell(tid, tokenAmount, payTokenAmount, msg.sender, user, feeTokenIds, feeTos, feeAmounts);
}
function _mortgage(
string memory tid,
uint256 tokenAmount,
address user
) private returns (uint256 nftTokenId, uint256 payTokenAmount) {
require(IFoundry(foundry).tokenExist(appId, tid), "TE");
require(tokenAmount > 0, "TAE");
require(tokenAmount <= _balanceOf[tid][user], "TAE");
nftTokenId = IMortgageNFT(mortgageNFT).mint(user, tid, tokenAmount);
payTokenAmount = _mortgageAddBase(nftTokenId, tid, 0, tokenAmount, user);
}
function _mortgageAdd(uint256 nftTokenId, uint256 tokenAmount) private returns (uint256 payTokenAmount) {
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
address user = IERC721(mortgageNFT).ownerOf(nftTokenId);
require(tokenAmount > 0, "TAE");
require(tokenAmount <= _balanceOf[tid][user], "TAE");
IMortgageNFT(mortgageNFT).add(nftTokenId, tokenAmount);
payTokenAmount = _mortgageAddBase(nftTokenId, tid, oldAmount, tokenAmount, user);
}
function _redeem(uint256 nftTokenId, uint256 tokenAmount) private returns (uint256 payTokenAmount) {
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
address user = IERC721(mortgageNFT).ownerOf(nftTokenId);
require(tokenAmount > 0, "TAE");
require(tokenAmount <= oldAmount, "TAE");
payTokenAmount = getPayTokenAmount(oldAmount - tokenAmount, tokenAmount);
IMortgageNFT(mortgageNFT).remove(nftTokenId, tokenAmount);
_balanceOf[tid][address(this)] -= tokenAmount;
_balanceOf[tid][user] += tokenAmount;
if (_payTokenIsERC20()) {
_transferFromERC20PayTokenFromSender(payTokenAmount);
} else {
require(msg.value >= payTokenAmount, "VE");
_refundETH(payTokenAmount);
}
emit Redeem(nftTokenId, tid, tokenAmount, payTokenAmount, msg.sender);
}
function _multiply(
string memory tid,
uint256 multiplyAmount,
address user
) private returns (uint256 nftTokenId, uint256 payTokenAmount) {
require(IFoundry(foundry).tokenExist(appId, tid), "TE");
require(multiplyAmount > 0, "TAE");
nftTokenId = IMortgageNFT(mortgageNFT).mint(user, tid, multiplyAmount);
payTokenAmount = _multiplyAddBase(nftTokenId, tid, 0, multiplyAmount);
}
function _multiplyAdd(uint256 nftTokenId, uint256 multiplyAmount) private returns (uint256 payTokenAmount) {
require(multiplyAmount > 0, "TAE");
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
IMortgageNFT(mortgageNFT).add(nftTokenId, multiplyAmount);
payTokenAmount = _multiplyAddBase(nftTokenId, tid, oldAmount, multiplyAmount);
}
function _cash(uint256 nftTokenId, uint256 tokenAmount) private returns (uint256 payTokenAmount) {
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
require(tokenAmount > 0, "TAE");
require(tokenAmount <= oldAmount, "TAE");
IMortgageNFT(mortgageNFT).remove(nftTokenId, tokenAmount);
(
uint256 sellAmount,
uint256[] memory feeTokenIds,
address[] memory feeTos,
uint256[] memory feeAmounts
) = _sellWithoutPay(address(this), tid, tokenAmount);
uint256 redeemPayTokenAmount = getPayTokenAmount(oldAmount - tokenAmount, tokenAmount);
require(sellAmount >= redeemPayTokenAmount, "CE");
payTokenAmount = sellAmount - redeemPayTokenAmount;
if (_payTokenIsERC20()) {
_transferERC20PayToken(msg.sender, payTokenAmount);
_batchTransferERC20PayTokenToNFTOwners(feeTokenIds, feeTos, feeAmounts);
} else {
_transferEth(msg.sender, payTokenAmount);
_batchTransferEthToNFTOwners(feeTokenIds, feeTos, feeAmounts);
}
emit Cash(nftTokenId, tid, tokenAmount, payTokenAmount, msg.sender, feeTokenIds, feeTos, feeAmounts);
}
function _buyWithoutPay(
address to,
string memory tid,
uint256 tokenAmount
)
private
returns (uint256 payTokenAmount, uint256[] memory feeTokenIds, address[] memory feeTos, uint256[] memory feeAmounts)
{
uint256 amount = getBuyPayTokenAmount(tid, tokenAmount);
uint256 totalFee;
(totalFee, feeTokenIds, feeTos, feeAmounts) = _getFee(tid, amount, buyFee);
payTokenAmount = amount + totalFee;
_totalSupply[tid] += tokenAmount;
_balanceOf[tid][to] += tokenAmount;
}
function _sellWithoutPay(
address from,
string memory tid,
uint256 tokenAmount
)
private
returns (uint256 payTokenAmount, uint256[] memory feeTokenIds, address[] memory feeTos, uint256[] memory feeAmounts)
{
uint256 amount = getSellPayTokenAmount(tid, tokenAmount);
uint256 totalFee;
(totalFee, feeTokenIds, feeTos, feeAmounts) = _getFee(tid, amount, sellFee);
payTokenAmount = amount - totalFee;
_totalSupply[tid] -= tokenAmount;
_balanceOf[tid][from] -= tokenAmount;
}
function _mortgageAddBase(
uint256 tokenId,
string memory tid,
uint256 oldAmount,
uint256 addAmount,
address user
) private returns (uint256 payTokenAmount) {
uint256 curveAmount = getPayTokenAmount(oldAmount, addAmount);
uint256 feeAmount = _mortgageFee(curveAmount);
_balanceOf[tid][user] -= addAmount;
_balanceOf[tid][address(this)] += addAmount;
payTokenAmount = curveAmount - feeAmount;
if (_payTokenIsERC20()) {
_transferERC20PayToken(msg.sender, payTokenAmount);
_transferERC20PayTokenToMortgageFeeRecipient(feeAmount);
} else {
_transferEth(msg.sender, payTokenAmount);
_transferEthToMortgageFeeRecipient(feeAmount);
}
emit Mortgage(tokenId, tid, addAmount, payTokenAmount, feeAmount, msg.sender);
}
function _multiplyAddBase(
uint256 nftTokenId,
string memory tid,
uint256 oldAmount,
uint256 multiplyAmount
) private returns (uint256 payTokenAmount) {
(
uint256 multiplyPayTokenAmount,
uint256[] memory feeTokenIds,
address[] memory feeTos,
uint256[] memory feeAmounts
) = _buyWithoutPay(address(this), tid, multiplyAmount);
uint256 curveAmount = getPayTokenAmount(oldAmount, multiplyAmount);
uint256 feeAmount = _mortgageFee(curveAmount);
uint256 mortAmount = curveAmount - feeAmount;
payTokenAmount = multiplyPayTokenAmount - mortAmount;
if (_payTokenIsERC20()) {
_transferFromERC20PayTokenFromSender(payTokenAmount);
_transferERC20PayTokenToMortgageFeeRecipient(feeAmount);
_batchTransferERC20PayTokenToNFTOwners(feeTokenIds, feeTos, feeAmounts);
} else {
require(msg.value >= payTokenAmount, "VE");
_transferEthToMortgageFeeRecipient(feeAmount);
_batchTransferEthToNFTOwners(feeTokenIds, feeTos, feeAmounts);
_refundETH(payTokenAmount);
}
emit Multiply(
nftTokenId,
tid,
multiplyAmount,
payTokenAmount,
feeAmount,
msg.sender,
feeTokenIds,
feeTos,
feeAmounts
);
}
function _merge(uint256 nftTokenId, uint256 otherNFTTokenId) private returns (uint256 payTokenAmount) {
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
(string memory otherTid, uint256 otherOldAmount) = IMortgageNFT(mortgageNFT).info(otherNFTTokenId);
require(keccak256(abi.encodePacked(tid)) == keccak256(abi.encodePacked(otherTid)), "TE");
IMortgageNFT(mortgageNFT).burn(otherNFTTokenId);
IMortgageNFT(mortgageNFT).add(nftTokenId, otherOldAmount);
uint256 curveAmount = getPayTokenAmount(oldAmount, otherOldAmount) - getPayTokenAmount(0, otherOldAmount);
uint256 feeAmount = _mortgageFee(curveAmount);
payTokenAmount = curveAmount - feeAmount;
if (_payTokenIsERC20()) {
_transferERC20PayToken(msg.sender, payTokenAmount);
_transferERC20PayTokenToMortgageFeeRecipient(feeAmount);
} else {
_transferEth(msg.sender, payTokenAmount);
_transferEthToMortgageFeeRecipient(feeAmount);
}
emit Merge(nftTokenId, tid, otherNFTTokenId, payTokenAmount, feeAmount, msg.sender);
}
function _split(
uint256 nftTokenId,
uint256 splitAmount
) private returns (uint256 payTokenAmount, uint256 newNFTTokenId) {
(string memory tid, uint256 oldAmount) = IMortgageNFT(mortgageNFT).info(nftTokenId);
require(splitAmount > 0, "SAE");
require(splitAmount < oldAmount, "SAE");
address user = IERC721(mortgageNFT).ownerOf(nftTokenId);
IMortgageNFT(mortgageNFT).remove(nftTokenId, splitAmount);
newNFTTokenId = IMortgageNFT(mortgageNFT).mint(user, tid, splitAmount);
payTokenAmount = getPayTokenAmount(oldAmount - splitAmount, splitAmount) - getPayTokenAmount(0, splitAmount);
if (_payTokenIsERC20()) {
_transferFromERC20PayTokenFromSender(payTokenAmount);
} else {
require(msg.value >= payTokenAmount, "VE");
_refundETH(payTokenAmount);
}
emit Split(nftTokenId, newNFTTokenId, tid, splitAmount, payTokenAmount, msg.sender);
}
function _getFee(
string memory tid,
uint256 amount,
uint256 buyOrSellFee
)
private
view
returns (uint256 totalFee, uint256[] memory tokenIds, address[] memory owners, uint256[] memory feeAmounts)
{
uint256[] memory percents;
(tokenIds, percents, , owners) = IPublicNFT(publicNFT).tidToInfos(tid);
feeAmounts = new uint256[](percents.length);
for (uint256 i = 0; i < percents.length; i++) {
uint256 feeAmount = (amount * buyOrSellFee * percents[i]) / totalPercent / feeDenominator;
feeAmounts[i] = feeAmount;
totalFee += feeAmount;
}
}
function _payTokenIsERC20() private view returns (bool) {
return payToken != address(0);
}
function _transferFromERC20PayTokenFromSender(uint256 value) private {
SafeERC20.safeTransferFrom(IERC20(payToken), msg.sender, address(this), value);
}
function _batchTransferEthToNFTOwners(
uint256[] memory tokenIds,
address[] memory tos,
uint256[] memory amounts
) private {
for (uint256 i = 0; i < amounts.length; i++) {
bool sup = ERC165Checker.supportsInterface(tos[i], type(IPublicNFTVault).interfaceId);
if (sup) {
_transferEthWithData(tokenIds[i], tos[i], amounts[i]);
} else {
_transferEth(tos[i], amounts[i]);
}
}
}
function _batchTransferERC20PayTokenToNFTOwners(
uint256[] memory tokenIds,
address[] memory tos,
uint256[] memory amounts
) private {
for (uint256 i = 0; i < amounts.length; i++) {
bool sup = ERC165Checker.supportsInterface(tos[i], type(IPublicNFTVault).interfaceId);
if (sup) {
_transferERC20PayTokenWithData(tokenIds[i], tos[i], amounts[i]);
} else {
_transferERC20PayToken(tos[i], amounts[i]);
}
}
}
function _transferEthToMortgageFeeRecipient(uint256 feeAmount) private {
_transferEth(IFoundry(foundry).mortgageFeeRecipient(appId), feeAmount);
}
function _transferERC20PayTokenToMortgageFeeRecipient(uint256 feeAmount) private {
_transferERC20PayToken(IFoundry(foundry).mortgageFeeRecipient(appId), feeAmount);
}
function _refundETH(uint256 needPay) private {
uint256 refund = msg.value - needPay;
if (refund > 0) {
_transferEth(msg.sender, refund);
}
}
function _transferEth(address to, uint256 value) private {
if (value > 0) {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "TEE");
}
}
function _transferEthWithData(uint256 tokenId, address to, uint256 value) private {
_transferEth(to, value);
bool success = IPublicNFTVault(to).recordReceiveBuySellFee(tokenId, value);
require(success, "TEWDE");
}
function _transferERC20PayToken(address to, uint256 value) private {
if (value > 0) {
SafeERC20.safeTransfer(IERC20(payToken), to, value);
}
}
function _transferERC20PayTokenWithData(uint256 tokenId, address to, uint256 value) private {
_transferERC20PayToken(to, value);
bool success = IPublicNFTVault(to).recordReceiveBuySellFee(tokenId, value);
require(success, "TE2WDE");
}
function _mortgageFee(uint256 amount) private view returns (uint256) {
return (IFoundry(foundry).mortgageFee(appId) * amount) / feeDenominator;
}
}
文件 14 的 15:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
文件 15 的 15:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
{
"compilationTarget": {
"contracts/Market.sol": "Market"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 800
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_foundry","type":"address"},{"internalType":"uint256","name":"_appId","type":"uint256"},{"internalType":"uint256","name":"_feeDenominator","type":"uint256"},{"internalType":"uint256","name":"_totalPercent","type":"uint256"},{"internalType":"address","name":"_curve","type":"address"},{"internalType":"address","name":"_payToken","type":"address"},{"internalType":"uint256","name":"_buyFee","type":"uint256"},{"internalType":"uint256","name":"_sellFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"feeTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"feeOwners","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"feeTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"feeOwners","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"}],"name":"Cash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"publicNFT","type":"address"},{"indexed":false,"internalType":"address","name":"mortgageNFT","type":"address"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"otherTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Merge","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Mortgage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"multiplyAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"feeTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"feeOwners","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"}],"name":"Multiply","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"feeTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"feeOwners","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"}],"name":"Sell","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tid","type":"string"},{"indexed":false,"internalType":"uint256","name":"splitAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Split","type":"event"},{"inputs":[],"name":"appId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"buy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"buyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"buyProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"cash","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"cashProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"curve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"foundry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getBuyPayTokenAmount","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"add","type":"uint256"}],"name":"getPayTokenAmount","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getSellPayTokenAmount","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_publicNFT","type":"address"},{"internalType":"address","name":"_mortgageNFT","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"otherNFTTokenId","type":"uint256"}],"name":"merge","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"otherNFTTokenId","type":"uint256"}],"name":"mergeProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"mortgage","outputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"mortgageAdd","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"mortgageAddProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mortgageNFT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"mortgageProxy","outputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"multiplyAmount","type":"uint256"}],"name":"multiply","outputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"multiplyAmount","type":"uint256"}],"name":"multiplyAdd","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"multiplyAmount","type":"uint256"}],"name":"multiplyAddProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"multiplyAmount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"multiplyProxy","outputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"payToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicNFT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"redeemProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"sell","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"sellProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"splitAmount","type":"uint256"}],"name":"split","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"internalType":"uint256","name":"newNFTTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftTokenId","type":"uint256"},{"internalType":"uint256","name":"splitAmount","type":"uint256"}],"name":"splitProxy","outputs":[{"internalType":"uint256","name":"payTokenAmount","type":"uint256"},{"internalType":"uint256","name":"newNFTTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"totalPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tid","type":"string"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]