编译器
0.6.12+commit.27d51765
文件 1 的 27:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 27:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 27:ERC165.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
_registerInterface(_INTERFACE_ID_ERC165);
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
文件 4 的 27:ERC721.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC721.sol";
import "./IERC721Metadata.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Receiver.sol";
import "../../introspection/ERC165.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../utils/EnumerableSet.sol";
import "../../utils/EnumerableMap.sol";
import "../../utils/Strings.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
using SafeMath for uint256;
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableMap for EnumerableMap.UintToAddressMap;
using Strings for uint256;
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
mapping (address => EnumerableSet.UintSet) private _holderTokens;
EnumerableMap.UintToAddressMap private _tokenOwners;
mapping (uint256 => address) private _tokenApprovals;
mapping (address => mapping (address => bool)) private _operatorApprovals;
string private _name;
string private _symbol;
mapping (uint256 => string) private _tokenURIs;
string private _baseURI;
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_registerInterface(_INTERFACE_ID_ERC721);
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _holderTokens[owner].length();
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
}
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) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = baseURI();
if (bytes(base).length == 0) {
return _tokenURI;
}
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return string(abi.encodePacked(base, tokenId.toString()));
}
function baseURI() public view virtual returns (string memory) {
return _baseURI;
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
return _holderTokens[owner].at(index);
}
function totalSupply() public view virtual override returns (uint256) {
return _tokenOwners.length();
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
(uint256 tokenId, ) = _tokenOwners.at(index);
return tokenId;
}
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 || ERC721.isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_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: transfer caller is not owner nor 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: transfer caller is not owner nor 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 _exists(uint256 tokenId) internal view virtual returns (bool) {
return _tokenOwners.contains(tokenId);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, 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);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
_holderTokens[owner].remove(tokenId);
_tokenOwners.remove(tokenId);
emit Transfer(owner, address(0), tokenId);
}
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_holderTokens[from].remove(tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(from, to, tokenId);
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes memory returndata = to.functionCall(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
), "ERC721: transfer to non ERC721Receiver implementer");
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}
文件 5 的 27:EnumerableMap.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableMap {
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
MapEntry[] _entries;
mapping (bytes32 => uint256) _indexes;
}
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) {
map._entries.push(MapEntry({ _key: key, _value: value }));
map._indexes[key] = map._entries.length;
return true;
} else {
map._entries[keyIndex - 1]._value = value;
return false;
}
}
function _remove(Map storage map, bytes32 key) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) {
uint256 toDeleteIndex = keyIndex - 1;
uint256 lastIndex = map._entries.length - 1;
MapEntry storage lastEntry = map._entries[lastIndex];
map._entries[toDeleteIndex] = lastEntry;
map._indexes[lastEntry._key] = toDeleteIndex + 1;
map._entries.pop();
delete map._indexes[key];
return true;
} else {
return false;
}
}
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._indexes[key] != 0;
}
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
require(map._entries.length > index, "EnumerableMap: index out of bounds");
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) return (false, 0);
return (true, map._entries[keyIndex - 1]._value);
}
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, "EnumerableMap: nonexistent key");
return map._entries[keyIndex - 1]._value;
}
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, errorMessage);
return map._entries[keyIndex - 1]._value;
}
struct UintToAddressMap {
Map _inner;
}
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
}
}
文件 6 的 27:EnumerableSet.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping (bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = toDeleteIndex + 1;
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
文件 7 的 27:EthPrimaryMarket.sol
pragma solidity >=0.6.10 <0.8.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "../../utils/SafeDecimalMath.sol";
import "../../interfaces/IFundV4.sol";
import "../../interfaces/IFundForPrimaryMarketV4.sol";
import "../../interfaces/ITrancheIndexV2.sol";
import "../../interfaces/IWrappedERC20.sol";
interface INonfungibleRedemptionDescriptor {
function tokenURI(
uint256 tokenId,
uint256 amountQ,
uint256 amountUnderlying,
uint256 seed
) external view returns (string memory);
function generateSeed(uint256 tokenId, uint256 amountQ) external view returns (uint256);
}
interface IERC4906 is IERC165, IERC721 {
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
contract EthPrimaryMarket is ReentrancyGuard, ITrancheIndexV2, Ownable, ERC721, IERC4906 {
event Created(address indexed account, uint256 underlying, uint256 outQ);
event Redeemed(address indexed account, uint256 inQ, uint256 underlying, uint256 feeQ);
event Split(address indexed account, uint256 inQ, uint256 outB, uint256 outR);
event Merged(
address indexed account,
uint256 outQ,
uint256 inB,
uint256 inR,
uint256 feeUnderlying
);
event RedemptionQueued(address indexed account, uint256 index, uint256 underlying);
event RedemptionFinalized(uint256 nextFinalizationIndex, uint256 inQ, uint256 underlying);
event RedemptionPopped(uint256 count, uint256 newHead, uint256 requiredUnderlying);
event RedemptionClaimed(address indexed account, uint256 index, uint256 underlying);
event FundCapUpdated(uint256 newCap);
event MergeFeeRateUpdated(uint256 newMergeFeeRate);
event RedemptionBoundsUpdated(uint256 newLowerBound, uint256 newUpperBound);
using Math for uint256;
using SafeMath for uint256;
using SafeDecimalMath for uint256;
using SafeERC20 for IERC20;
struct QueuedRedemption {
uint256 amountQ;
uint256 previousPrefixSum;
uint256 seed;
}
struct RedemptionRate {
uint256 nextIndex;
uint256 underlyingPerQ;
}
uint256 private constant MAX_MERGE_FEE_RATE = 0.01e18;
uint256 public constant redemptionFeeRate = 0;
address public immutable fund;
IERC20 private immutable _tokenUnderlying;
INonfungibleRedemptionDescriptor private immutable _descriptor;
uint256 public mergeFeeRate;
uint256 public fundCap;
mapping(uint256 => QueuedRedemption) public queuedRedemptions;
uint256 public claimableUnderlying;
uint256 public redemptionQueueHead;
uint256 public redemptionQueueTail;
mapping(uint256 => RedemptionRate) public redemptionRates;
uint256 public redemptionRateSize;
uint256 public minRedemptionBound;
uint256 public maxRedemptionBound;
constructor(
address fund_,
uint256 mergeFeeRate_,
uint256 fundCap_,
string memory name_,
string memory symbol_,
address descriptor_,
uint256 minRedemptionBound_,
uint256 maxRedemptionBound_
) public Ownable() ERC721(name_, symbol_) {
fund = fund_;
_tokenUnderlying = IERC20(IFundV4(fund_).tokenUnderlying());
_updateMergeFeeRate(mergeFeeRate_);
_updateFundCap(fundCap_);
_descriptor = INonfungibleRedemptionDescriptor(descriptor_);
_updateRedemptionBounds(minRedemptionBound_, maxRedemptionBound_);
_registerInterface(bytes4(0x49064906));
}
function getCreation(uint256 underlying) public view returns (uint256 outQ) {
uint256 fundUnderlying = IFundV4(fund).getTotalUnderlying();
uint256 fundEquivalentTotalQ = IFundV4(fund).getEquivalentTotalQ();
require(fundUnderlying.add(underlying) <= fundCap, "Exceed fund cap");
if (fundEquivalentTotalQ == 0) {
outQ = underlying.mul(IFundV4(fund).underlyingDecimalMultiplier());
uint256 splitRatio = IFundV4(fund).splitRatio();
require(splitRatio != 0, "Fund is not initialized");
uint256 settledDay = IFundV4(fund).currentDay() - 1 days;
uint256 underlyingPrice = IFundV4(fund).twapOracle().getTwap(settledDay);
(uint256 navB, uint256 navR) = IFundV4(fund).historicalNavs(settledDay);
outQ = outQ.mul(underlyingPrice).div(splitRatio).divideDecimal(navB.add(navR));
} else {
require(
fundUnderlying != 0,
"Cannot create QUEEN for fund with shares but no underlying"
);
outQ = underlying.mul(fundEquivalentTotalQ).div(fundUnderlying);
}
}
function getCreationForQ(uint256 minOutQ) external view returns (uint256 underlying) {
uint256 fundUnderlying = IFundV4(fund).getTotalUnderlying();
uint256 fundEquivalentTotalQ = IFundV4(fund).getEquivalentTotalQ();
require(fundEquivalentTotalQ > 0, "Cannot calculate creation for empty fund");
return minOutQ.mul(fundUnderlying).add(fundEquivalentTotalQ - 1).div(fundEquivalentTotalQ);
}
function _getRedemption(uint256 inQ) private view returns (uint256 underlying) {
uint256 fundUnderlying = IFundV4(fund).getTotalUnderlying();
uint256 fundEquivalentTotalQ = IFundV4(fund).getEquivalentTotalQ();
underlying = inQ.mul(fundUnderlying).div(fundEquivalentTotalQ);
}
function getRedemption(uint256 inQ) public view returns (uint256 underlying, uint256 feeQ) {
underlying = _getRedemption(inQ);
feeQ = 0;
}
function getRedemptionForUnderlying(uint256 minUnderlying) external view returns (uint256 inQ) {
uint256 fundUnderlying = IFundV4(fund).getTotalUnderlying();
uint256 fundEquivalentTotalQ = IFundV4(fund).getEquivalentTotalQ();
uint256 inQAfterFee =
minUnderlying.mul(fundEquivalentTotalQ).add(fundUnderlying - 1).div(fundUnderlying);
return inQAfterFee.divideDecimal(1e18 - redemptionFeeRate);
}
function getSplit(uint256 inQ) public view returns (uint256 outB) {
return inQ.multiplyDecimal(IFundV4(fund).splitRatio());
}
function getSplitForB(uint256 minOutB) external view returns (uint256 inQ) {
uint256 splitRatio = IFundV4(fund).splitRatio();
return minOutB.mul(1e18).add(splitRatio.sub(1)).div(splitRatio);
}
function getMerge(uint256 inB) public view returns (uint256 outQ, uint256 feeQ) {
uint256 outQBeforeFee = inB.divideDecimal(IFundV4(fund).splitRatio());
feeQ = outQBeforeFee.multiplyDecimal(mergeFeeRate);
outQ = outQBeforeFee.sub(feeQ);
}
function getMergeForQ(uint256 minOutQ) external view returns (uint256 inB) {
uint256 outQBeforeFee = minOutQ.divideDecimal(1e18 - mergeFeeRate);
inB = outQBeforeFee.mul(IFundV4(fund).splitRatio()).add(1e18 - 1).div(1e18);
}
function getNewRedemptionQueueHead() public view returns (uint256) {
uint256 available = _tokenUnderlying.balanceOf(fund);
uint256 l = redemptionQueueHead;
uint256 startPrefixSum = queuedRedemptions[l].previousPrefixSum;
uint256 rateSize = redemptionRateSize;
uint256 rateIndex = getRedemptionRateIndex(l);
uint256 r = l;
while (rateIndex < rateSize) {
r = redemptionRates[rateIndex].nextIndex;
uint256 endPrefixSum = queuedRedemptions[r].previousPrefixSum;
uint256 underlying =
(endPrefixSum - startPrefixSum).multiplyDecimalPrecise(
redemptionRates[rateIndex].underlyingPerQ
);
if (available < underlying) {
break;
}
available -= underlying;
l = r;
startPrefixSum = endPrefixSum;
rateIndex += 1;
}
if (rateIndex >= rateSize) {
return r;
}
uint256 underlyingPerQ = redemptionRates[rateIndex].underlyingPerQ;
while (l + 1 < r) {
uint256 m = (l + r) / 2;
uint256 underlying =
(queuedRedemptions[m].previousPrefixSum - startPrefixSum).multiplyDecimalPrecise(
underlyingPerQ
);
if (underlying <= available) {
l = m;
} else {
r = m;
}
}
return l;
}
function getRedemptionRateIndexOfHead() external view returns (uint256) {
return getRedemptionRateIndex(redemptionQueueHead);
}
function getRedemptionRateIndex(uint256 index) public view returns (uint256) {
uint256 l = 0;
uint256 r = redemptionRateSize;
if (r == 0) return 0;
if (redemptionRates[r - 1].nextIndex <= index) {
return r;
}
while (l + 1 < r) {
uint256 m = (l + r) / 2;
if (redemptionRates[m - 1].nextIndex <= index) {
l = m;
} else {
r = m;
}
}
return l;
}
function getRedemptionUnderlying(uint256 index) public view returns (uint256) {
uint256 rateIndex = getRedemptionRateIndex(index);
return
rateIndex < redemptionRateSize
? queuedRedemptions[index].amountQ.multiplyDecimalPrecise(
redemptionRates[rateIndex].underlyingPerQ
)
: 0;
}
function getQueuedRedemptions(address account)
external
view
returns (
uint256[] memory indices,
uint256[] memory rateIndices,
uint256 rateIndexOfHead,
uint256 newRedemptionQueueHead,
uint256 amountQ,
uint256 underlying
)
{
newRedemptionQueueHead = getNewRedemptionQueueHead();
uint256 count = balanceOf(account);
indices = new uint256[](count);
rateIndices = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
uint256 index = tokenOfOwnerByIndex(account, i);
indices[i] = index;
rateIndices[i] = getRedemptionRateIndex(index);
amountQ += queuedRedemptions[index].amountQ;
if (index < newRedemptionQueueHead) {
underlying += getRedemptionUnderlying(index);
}
}
rateIndexOfHead = getRedemptionRateIndex(redemptionQueueHead);
}
function getNextFinalizationIndex() public view returns (uint256 index) {
if (redemptionRateSize == 0) return 0;
return redemptionRates[redemptionRateSize - 1].nextIndex;
}
function canBeRemovedFromFund() external view returns (bool) {
return redemptionQueueHead == redemptionQueueTail;
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId));
uint256 amountQ = queuedRedemptions[tokenId].amountQ;
uint256 amountUnderlying = getRedemptionUnderlying(tokenId);
return
_descriptor.tokenURI(
tokenId,
amountQ,
amountUnderlying,
queuedRedemptions[tokenId].seed
);
}
function baseURI() public view override returns (string memory) {}
function create(
address recipient,
uint256 minOutQ,
uint256 version
) external nonReentrant returns (uint256 outQ) {
uint256 underlying = _tokenUnderlying.balanceOf(address(this)).sub(claimableUnderlying);
outQ = getCreation(underlying);
require(outQ >= minOutQ && outQ > 0, "Min QUEEN created");
IFundForPrimaryMarketV4(fund).primaryMarketMint(TRANCHE_Q, recipient, outQ, version);
_tokenUnderlying.safeTransfer(fund, underlying);
emit Created(recipient, underlying, outQ);
}
function queueRedemption(
address recipient,
uint256 inQ,
uint256,
uint256 version
) external nonReentrant returns (uint256 underlying, uint256 index) {
require(inQ >= minRedemptionBound && inQ <= maxRedemptionBound, "Invalid amount");
underlying = 0;
index = redemptionQueueTail;
QueuedRedemption storage newRedemption = queuedRedemptions[index];
newRedemption.amountQ = inQ;
queuedRedemptions[index + 1].previousPrefixSum = newRedemption.previousPrefixSum + inQ;
redemptionQueueTail = index + 1;
IFundForPrimaryMarketV4(fund).primaryMarketBurn(TRANCHE_Q, msg.sender, inQ, version);
IFundForPrimaryMarketV4(fund).primaryMarketMint(TRANCHE_Q, address(this), inQ, version);
newRedemption.seed = _descriptor.generateSeed(index, inQ);
emit RedemptionQueued(recipient, index, inQ);
_safeMint(recipient, index);
}
function finalizeRedemptions(uint256 count) external {
require(msg.sender == IFundV4(fund).strategy(), "Only Strategy");
uint256 oldFinalizedIndex = getNextFinalizationIndex();
uint256 newFinalizedIndex = oldFinalizedIndex.add(count);
require(newFinalizedIndex <= redemptionQueueTail, "Redemption queue out of bound");
uint256 amountQ =
queuedRedemptions[newFinalizedIndex].previousPrefixSum -
queuedRedemptions[oldFinalizedIndex].previousPrefixSum;
(uint256 underlying, ) = getRedemption(amountQ);
uint256 version = IFundV4(fund).getRebalanceSize();
IFundForPrimaryMarketV4(fund).primaryMarketBurn(TRANCHE_Q, address(this), amountQ, version);
IFundForPrimaryMarketV4(fund).primaryMarketAddDebtAndFee(underlying, 0);
emit Redeemed(address(0), amountQ, underlying, 0);
redemptionRates[redemptionRateSize++] = RedemptionRate({
nextIndex: newFinalizedIndex,
underlyingPerQ: underlying.divideDecimalPrecise(amountQ)
});
emit RedemptionFinalized(newFinalizedIndex, amountQ, underlying);
emit BatchMetadataUpdate(oldFinalizedIndex, newFinalizedIndex - 1);
}
function popRedemptionQueue(uint256 count, uint256 rateIndexOfHead) external nonReentrant {
_popRedemptionQueue(count, rateIndexOfHead);
}
function _popRedemptionQueue(uint256 count, uint256 rateIndexOfHead) private {
uint256 oldHead = redemptionQueueHead;
uint256 oldTail = getNextFinalizationIndex();
uint256 newHead;
if (count == 0) {
if (oldHead == oldTail) {
return;
}
newHead = oldTail;
} else {
newHead = oldHead.add(count);
require(newHead <= oldTail, "Redemption queue out of bound");
}
require(rateIndexOfHead < redemptionRateSize, "Invalid rate index");
require(
rateIndexOfHead == 0 || oldHead >= redemptionRates[rateIndexOfHead - 1].nextIndex,
"Invalid rate index"
);
require(oldHead < redemptionRates[rateIndexOfHead].nextIndex, "Invalid rate index");
uint256 startIndex = oldHead;
uint256 requiredUnderlying = 0;
while (startIndex < newHead) {
uint256 nextIndex = redemptionRates[rateIndexOfHead].nextIndex;
uint256 endIndex = newHead.min(nextIndex);
requiredUnderlying = requiredUnderlying.add(
redemptionRates[rateIndexOfHead].underlyingPerQ.multiplyDecimalPrecise(
queuedRedemptions[endIndex].previousPrefixSum -
queuedRedemptions[startIndex].previousPrefixSum
)
);
if (endIndex == nextIndex) {
rateIndexOfHead++;
}
startIndex = endIndex;
}
if (newHead == oldTail) {
uint256 debt = IFundV4(fund).getTotalDebt();
require(debt >= requiredUnderlying);
requiredUnderlying = debt;
}
require(
requiredUnderlying <= _tokenUnderlying.balanceOf(fund),
"Not enough underlying in fund"
);
claimableUnderlying = claimableUnderlying.add(requiredUnderlying);
IFundForPrimaryMarketV4(fund).primaryMarketPayDebt(requiredUnderlying);
redemptionQueueHead = newHead;
emit RedemptionPopped(newHead - oldHead, newHead, requiredUnderlying);
}
function claimRedemptions(
uint256[] calldata indices,
uint256[] calldata rateIndices,
uint256 rateIndexOfHead
) external nonReentrant returns (uint256 underlying) {
underlying = _claimRedemptions(indices, rateIndices, rateIndexOfHead);
_tokenUnderlying.safeTransfer(msg.sender, underlying);
}
function claimRedemptionsAndUnwrap(
uint256[] calldata indices,
uint256[] calldata rateIndices,
uint256 rateIndexOfHead
) external nonReentrant returns (uint256 underlying) {
underlying = _claimRedemptions(indices, rateIndices, rateIndexOfHead);
IWrappedERC20(address(_tokenUnderlying)).withdraw(underlying);
(bool success, ) = msg.sender.call{value: underlying}("");
require(success, "Transfer failed");
}
function _claimRedemptions(
uint256[] calldata indices,
uint256[] calldata rateIndices,
uint256 rateIndexOfHead
) private returns (uint256 underlying) {
uint256 count = indices.length;
require(count == rateIndices.length, "Invalid rate indices");
if (count == 0) {
return 0;
}
uint256 head = redemptionQueueHead;
if (indices[count - 1] >= head) {
_popRedemptionQueue(indices[count - 1] - head + 1, rateIndexOfHead);
}
for (uint256 i = 0; i < count; i++) {
require(i == 0 || indices[i] > indices[i - 1], "Indices out of order");
require(rateIndices[i] < redemptionRateSize, "Invalid rate index");
require(
indices[i] < redemptionRates[rateIndices[i]].nextIndex &&
indices[i] >= redemptionRates[rateIndices[i] - 1].nextIndex,
"Invalid index"
);
QueuedRedemption storage redemption = queuedRedemptions[indices[i]];
uint256 redemptionUnderlying =
redemption.amountQ.multiplyDecimalPrecise(
redemptionRates[rateIndices[i]].underlyingPerQ
);
require(
ownerOf(indices[i]) == msg.sender && redemption.amountQ != 0,
"Invalid redemption index"
);
underlying = underlying.add(redemptionUnderlying);
emit RedemptionClaimed(msg.sender, indices[i], redemptionUnderlying);
delete queuedRedemptions[indices[i]];
_burn(indices[i]);
}
claimableUnderlying = claimableUnderlying.sub(underlying);
}
function split(
address recipient,
uint256 inQ,
uint256 version
) external returns (uint256 outB) {
outB = getSplit(inQ);
IFundForPrimaryMarketV4(fund).primaryMarketBurn(TRANCHE_Q, msg.sender, inQ, version);
IFundForPrimaryMarketV4(fund).primaryMarketMint(TRANCHE_B, recipient, outB, version);
IFundForPrimaryMarketV4(fund).primaryMarketMint(TRANCHE_R, recipient, outB, version);
emit Split(recipient, inQ, outB, outB);
}
function merge(
address recipient,
uint256 inB,
uint256 version
) external returns (uint256 outQ) {
uint256 feeQ;
(outQ, feeQ) = getMerge(inB);
IFundForPrimaryMarketV4(fund).primaryMarketBurn(TRANCHE_B, msg.sender, inB, version);
IFundForPrimaryMarketV4(fund).primaryMarketBurn(TRANCHE_R, msg.sender, inB, version);
IFundForPrimaryMarketV4(fund).primaryMarketMint(TRANCHE_Q, recipient, outQ, version);
IFundForPrimaryMarketV4(fund).primaryMarketAddDebtAndFee(0, feeQ);
emit Merged(recipient, outQ, inB, inB, feeQ);
}
function settle(uint256 day) external onlyFund {}
function _updateFundCap(uint256 newCap) private {
fundCap = newCap;
emit FundCapUpdated(newCap);
}
function updateFundCap(uint256 newCap) external onlyOwner {
_updateFundCap(newCap);
}
function _updateMergeFeeRate(uint256 newMergeFeeRate) private {
require(newMergeFeeRate <= MAX_MERGE_FEE_RATE, "Exceed max merge fee rate");
mergeFeeRate = newMergeFeeRate;
emit MergeFeeRateUpdated(newMergeFeeRate);
}
function updateMergeFeeRate(uint256 newMergeFeeRate) external onlyOwner {
_updateMergeFeeRate(newMergeFeeRate);
}
function _updateRedemptionBounds(uint256 newMinRedemptionBound, uint256 newMaxRedemptionBound)
private
{
require(newMinRedemptionBound <= newMaxRedemptionBound, "Invalid redemption bounds");
minRedemptionBound = newMinRedemptionBound;
maxRedemptionBound = newMaxRedemptionBound;
emit RedemptionBoundsUpdated(newMinRedemptionBound, newMaxRedemptionBound);
}
function updateRedemptionBounds(uint256 newMinRedemptionBound, uint256 newMaxRedemptionBound)
external
onlyOwner
{
_updateRedemptionBounds(newMinRedemptionBound, newMaxRedemptionBound);
}
receive() external payable {}
modifier onlyFund() {
require(msg.sender == fund, "Only fund");
_;
}
}
文件 8 的 27:IERC165.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 27:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 10 的 27:IERC721.sol
pragma solidity >=0.6.2 <0.8.0;
import "../../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) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
文件 11 的 27:IERC721Enumerable.sol
pragma solidity >=0.6.2 <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 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 12 的 27:IERC721Metadata.sol
pragma solidity >=0.6.2 <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);
}
文件 13 的 27:IERC721Receiver.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
文件 14 的 27:IFundForPrimaryMarketV4.sol
pragma solidity >=0.6.10 <0.8.0;
interface IFundForPrimaryMarketV4 {
function primaryMarketMint(
uint256 tranche,
address account,
uint256 amount,
uint256 version
) external;
function primaryMarketBurn(
uint256 tranche,
address account,
uint256 amount,
uint256 version
) external;
function primaryMarketTransferUnderlying(
address recipient,
uint256 amount,
uint256 feeQ
) external;
function primaryMarketAddDebtAndFee(uint256 amount, uint256 feeQ) external;
function primaryMarketPayDebt(uint256 amount) external;
}
文件 15 的 27:IFundV3.sol
pragma solidity >=0.6.10 <0.8.0;
pragma experimental ABIEncoderV2;
import "./ITwapOracleV2.sol";
interface IFundV3 {
struct Rebalance {
uint256 ratioB2Q;
uint256 ratioR2Q;
uint256 ratioBR;
uint256 timestamp;
}
function tokenUnderlying() external view returns (address);
function tokenQ() external view returns (address);
function tokenB() external view returns (address);
function tokenR() external view returns (address);
function tokenShare(uint256 tranche) external view returns (address);
function primaryMarket() external view returns (address);
function primaryMarketUpdateProposal() external view returns (address, uint256);
function strategy() external view returns (address);
function strategyUpdateProposal() external view returns (address, uint256);
function underlyingDecimalMultiplier() external view returns (uint256);
function twapOracle() external view returns (ITwapOracleV2);
function feeCollector() external view returns (address);
function endOfDay(uint256 timestamp) external pure returns (uint256);
function trancheTotalSupply(uint256 tranche) external view returns (uint256);
function trancheBalanceOf(uint256 tranche, address account) external view returns (uint256);
function trancheAllBalanceOf(address account)
external
view
returns (
uint256,
uint256,
uint256
);
function trancheBalanceVersion(address account) external view returns (uint256);
function trancheAllowance(
uint256 tranche,
address owner,
address spender
) external view returns (uint256);
function trancheAllowanceVersion(address owner, address spender)
external
view
returns (uint256);
function trancheTransfer(
uint256 tranche,
address recipient,
uint256 amount,
uint256 version
) external;
function trancheTransferFrom(
uint256 tranche,
address sender,
address recipient,
uint256 amount,
uint256 version
) external;
function trancheApprove(
uint256 tranche,
address spender,
uint256 amount,
uint256 version
) external;
function getRebalanceSize() external view returns (uint256);
function getRebalance(uint256 index) external view returns (Rebalance memory);
function getRebalanceTimestamp(uint256 index) external view returns (uint256);
function currentDay() external view returns (uint256);
function splitRatio() external view returns (uint256);
function historicalSplitRatio(uint256 version) external view returns (uint256);
function fundActivityStartTime() external view returns (uint256);
function isFundActive(uint256 timestamp) external view returns (bool);
function getEquivalentTotalB() external view returns (uint256);
function getEquivalentTotalQ() external view returns (uint256);
function historicalEquivalentTotalB(uint256 timestamp) external view returns (uint256);
function historicalNavs(uint256 timestamp) external view returns (uint256 navB, uint256 navR);
function extrapolateNav(uint256 price)
external
view
returns (
uint256,
uint256,
uint256
);
function doRebalance(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 index
)
external
view
returns (
uint256 newAmountQ,
uint256 newAmountB,
uint256 newAmountR
);
function batchRebalance(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 fromIndex,
uint256 toIndex
)
external
view
returns (
uint256 newAmountQ,
uint256 newAmountB,
uint256 newAmountR
);
function refreshBalance(address account, uint256 targetVersion) external;
function refreshAllowance(
address owner,
address spender,
uint256 targetVersion
) external;
function shareTransfer(
address sender,
address recipient,
uint256 amount
) external;
function shareTransferFrom(
address spender,
address sender,
address recipient,
uint256 amount
) external returns (uint256 newAllowance);
function shareIncreaseAllowance(
address sender,
address spender,
uint256 addedValue
) external returns (uint256 newAllowance);
function shareDecreaseAllowance(
address sender,
address spender,
uint256 subtractedValue
) external returns (uint256 newAllowance);
function shareApprove(
address owner,
address spender,
uint256 amount
) external;
function historicalUnderlying(uint256 timestamp) external view returns (uint256);
function getTotalUnderlying() external view returns (uint256);
function getStrategyUnderlying() external view returns (uint256);
function getTotalDebt() external view returns (uint256);
event RebalanceTriggered(
uint256 indexed index,
uint256 indexed day,
uint256 navSum,
uint256 navB,
uint256 navROrZero,
uint256 ratioB2Q,
uint256 ratioR2Q,
uint256 ratioBR
);
event Settled(uint256 indexed day, uint256 navB, uint256 navR, uint256 interestRate);
event InterestRateUpdated(uint256 baseInterestRate, uint256 floatingInterestRate);
event BalancesRebalanced(
address indexed account,
uint256 version,
uint256 balanceQ,
uint256 balanceB,
uint256 balanceR
);
event AllowancesRebalanced(
address indexed owner,
address indexed spender,
uint256 version,
uint256 allowanceQ,
uint256 allowanceB,
uint256 allowanceR
);
}
文件 16 的 27:IFundV4.sol
pragma solidity >=0.6.10 <0.8.0;
import "./IFundV3.sol";
interface IFundV4 is IFundV3 {
function getRelativeIncome(uint256 day)
external
view
returns (uint256 incomeOverQ, uint256 incomeOverB);
}
文件 17 的 27:ITrancheIndexV2.sol
pragma solidity >=0.6.10 <0.8.0;
abstract contract ITrancheIndexV2 {
uint256 internal constant TRANCHE_Q = 0;
uint256 internal constant TRANCHE_B = 1;
uint256 internal constant TRANCHE_R = 2;
uint256 internal constant TRANCHE_COUNT = 3;
}
文件 18 的 27:ITwapOracle.sol
pragma solidity >=0.6.10 <0.8.0;
interface ITwapOracle {
enum UpdateType {PRIMARY, SECONDARY, OWNER, CHAINLINK, UNISWAP_V2}
function getTwap(uint256 timestamp) external view returns (uint256);
}
文件 19 的 27:ITwapOracleV2.sol
pragma solidity >=0.6.10 <0.8.0;
import "./ITwapOracle.sol";
interface ITwapOracleV2 is ITwapOracle {
function getLatest() external view returns (uint256);
}
文件 20 的 27:IWrappedERC20.sol
pragma solidity >=0.6.10 <0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWrappedERC20 is IERC20 {
function deposit() external payable;
function withdraw(uint256 wad) external;
}
文件 21 的 27:Math.sol
pragma solidity >=0.6.0 <0.8.0;
library Math {
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 / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 22 的 27:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 23 的 27:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 24 的 27:SafeDecimalMath.sol
pragma solidity >=0.6.10 <0.8.0;
import "@openzeppelin/contracts/math/SafeMath.sol";
library SafeDecimalMath {
using SafeMath for uint256;
uint256 private constant decimals = 18;
uint256 private constant highPrecisionDecimals = 27;
uint256 private constant UNIT = 10**uint256(decimals);
uint256 private constant PRECISE_UNIT = 10**uint256(highPrecisionDecimals);
uint256 private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR =
10**uint256(highPrecisionDecimals - decimals);
function multiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(y).div(UNIT);
}
function multiplyDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(y).div(PRECISE_UNIT);
}
function divideDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(UNIT).div(y);
}
function divideDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(PRECISE_UNIT).div(y);
}
function decimalToPreciseDecimal(uint256 i) internal pure returns (uint256) {
return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
}
function preciseDecimalToDecimal(uint256 i) internal pure returns (uint256) {
uint256 quotientTimesTen = i.mul(10).div(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen = quotientTimesTen.add(10);
}
return quotientTimesTen.div(10);
}
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
return c / a != b ? type(uint256).max : c;
}
function saturatingMultiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return saturatingMul(x, y).div(UNIT);
}
}
文件 25 的 27:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 26 的 27:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 27 的 27:Strings.sol
pragma solidity >=0.6.0 <0.8.0;
library Strings {
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = bytes1(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}
{
"compilationTarget": {
"contracts/strategy/eth/EthPrimaryMarket.sol": "EthPrimaryMarket"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"fund_","type":"address"},{"internalType":"uint256","name":"mergeFeeRate_","type":"uint256"},{"internalType":"uint256","name":"fundCap_","type":"uint256"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"descriptor_","type":"address"},{"internalType":"uint256","name":"minRedemptionBound_","type":"uint256"},{"internalType":"uint256","name":"maxRedemptionBound_","type":"uint256"}],"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":"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":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outQ","type":"uint256"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"FundCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMergeFeeRate","type":"uint256"}],"name":"MergeFeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"outQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"inB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"inR","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeUnderlying","type":"uint256"}],"name":"Merged","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"inQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"underlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeQ","type":"uint256"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLowerBound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newUpperBound","type":"uint256"}],"name":"RedemptionBoundsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"underlying","type":"uint256"}],"name":"RedemptionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nextFinalizationIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"inQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"underlying","type":"uint256"}],"name":"RedemptionFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newHead","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requiredUnderlying","type":"uint256"}],"name":"RedemptionPopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"underlying","type":"uint256"}],"name":"RedemptionQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"inQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outR","type":"uint256"}],"name":"Split","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":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","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":[],"name":"canBeRemovedFromFund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"indices","type":"uint256[]"},{"internalType":"uint256[]","name":"rateIndices","type":"uint256[]"},{"internalType":"uint256","name":"rateIndexOfHead","type":"uint256"}],"name":"claimRedemptions","outputs":[{"internalType":"uint256","name":"underlying","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"indices","type":"uint256[]"},{"internalType":"uint256[]","name":"rateIndices","type":"uint256[]"},{"internalType":"uint256","name":"rateIndexOfHead","type":"uint256"}],"name":"claimRedemptionsAndUnwrap","outputs":[{"internalType":"uint256","name":"underlying","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimableUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minOutQ","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"create","outputs":[{"internalType":"uint256","name":"outQ","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"finalizeRedemptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"underlying","type":"uint256"}],"name":"getCreation","outputs":[{"internalType":"uint256","name":"outQ","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minOutQ","type":"uint256"}],"name":"getCreationForQ","outputs":[{"internalType":"uint256","name":"underlying","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inB","type":"uint256"}],"name":"getMerge","outputs":[{"internalType":"uint256","name":"outQ","type":"uint256"},{"internalType":"uint256","name":"feeQ","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minOutQ","type":"uint256"}],"name":"getMergeForQ","outputs":[{"internalType":"uint256","name":"inB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewRedemptionQueueHead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextFinalizationIndex","outputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getQueuedRedemptions","outputs":[{"internalType":"uint256[]","name":"indices","type":"uint256[]"},{"internalType":"uint256[]","name":"rateIndices","type":"uint256[]"},{"internalType":"uint256","name":"rateIndexOfHead","type":"uint256"},{"internalType":"uint256","name":"newRedemptionQueueHead","type":"uint256"},{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"underlying","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inQ","type":"uint256"}],"name":"getRedemption","outputs":[{"internalType":"uint256","name":"underlying","type":"uint256"},{"internalType":"uint256","name":"feeQ","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minUnderlying","type":"uint256"}],"name":"getRedemptionForUnderlying","outputs":[{"internalType":"uint256","name":"inQ","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRedemptionRateIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRateIndexOfHead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRedemptionUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inQ","type":"uint256"}],"name":"getSplit","outputs":[{"internalType":"uint256","name":"outB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minOutB","type":"uint256"}],"name":"getSplitForB","outputs":[{"internalType":"uint256","name":"inQ","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":[],"name":"maxRedemptionBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"inB","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"merge","outputs":[{"internalType":"uint256","name":"outQ","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mergeFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRedemptionBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":"count","type":"uint256"},{"internalType":"uint256","name":"rateIndexOfHead","type":"uint256"}],"name":"popRedemptionQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"inQ","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"queueRedemption","outputs":[{"internalType":"uint256","name":"underlying","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"queuedRedemptions","outputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"previousPrefixSum","type":"uint256"},{"internalType":"uint256","name":"seed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionQueueHead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionQueueTail","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRateSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"redemptionRates","outputs":[{"internalType":"uint256","name":"nextIndex","type":"uint256"},{"internalType":"uint256","name":"underlyingPerQ","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"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":"uint256","name":"day","type":"uint256"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"inQ","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"split","outputs":[{"internalType":"uint256","name":"outB","type":"uint256"}],"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":"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":"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":[{"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"updateFundCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMergeFeeRate","type":"uint256"}],"name":"updateMergeFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMinRedemptionBound","type":"uint256"},{"internalType":"uint256","name":"newMaxRedemptionBound","type":"uint256"}],"name":"updateRedemptionBounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]