编译器
0.8.17+commit.8df45f5f
文件 1 的 6:AccessControl.sol
pragma solidity =0.8.17;
contract AccessControl {
address public multisig;
mapping(address => mapping(address => bool)) public workers;
event MultisigUpdated(
address newMultisig
);
event WorkerAdded(
address wiseGroup,
address newWorker
);
event WorkerRemoved(
address wiseGroup,
address existingWorker
);
constructor() {
multisig = tx.origin;
}
modifier onlyMultisig() {
require(
msg.sender == multisig,
"AccessControl: NOT_MULTISIG"
);
_;
}
modifier onlyWiseWorker(
address _group
) {
require(
workers[_group][msg.sender] == true,
"AccessControl: NOT_WORKER"
);
_;
}
function updateMultisig(
address _newMultisig
)
external
onlyMultisig
{
require(
_newMultisig > address(0),
"AccessControl: EMPTY_ADDRESS"
);
multisig = _newMultisig;
emit MultisigUpdated(
_newMultisig
);
}
function addWorker(
address _group,
address _worker
)
external
onlyMultisig
{
_addWorker(
_group,
_worker
);
}
function _addWorker(
address _group,
address _worker
)
internal
{
workers[_group][_worker] = true;
emit WorkerAdded(
_group,
_worker
);
}
function removeWorker(
address _group,
address _worker
)
external
onlyMultisig
{
workers[_group][_worker] = false;
emit WorkerRemoved(
_group,
_worker
);
}
}
文件 2 的 6:IChainLink.sol
pragma solidity =0.8.17;
interface IChainLink {
function decimals()
external
view
returns (uint8);
function latestAnswer()
external
view
returns (uint256);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answerdInRound
);
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function phaseId()
external
view
returns(
uint16 phaseId
);
function aggregator()
external
view
returns (address);
}
文件 3 的 6:ILiquidPool.sol
pragma solidity =0.8.17;
interface ILiquidPool {
function depositFunds(
uint256 _amount,
address _depositor
)
external
returns (uint256);
function withdrawFunds(
uint256 _shares,
address _user
)
external
returns (uint256);
function borrowFunds(
address _borrowAddress,
uint256 _borrowAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external;
function borrowMoreFunds(
address _borrowAddress,
uint256 _borrowAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external;
function paybackFunds(
uint256 _payAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
returns (uint256);
function liquidateNFT(
address _liquidator,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
returns (uint256);
function getLoanOwner(
address _nft,
uint256 _tokenID
)
external
view
returns (address);
function withdrawFee()
external;
function poolToken()
external
view
returns (address);
function calculateWithdrawAmount(
uint256 _shares
)
external
view
returns (uint256);
function lockFeeDestination()
external;
function changeFeeDestinationAddress(
address _newFeeDestinationAddress
)
external;
function expandPool(
address _nftAddress
)
external;
function addCollection(
address _nftAddress
)
external;
}
文件 4 的 6:LiquidRouter.sol
pragma solidity =0.8.17;
import "./ILiquidPool.sol";
import "./IChainLink.sol";
import "./RouterEvents.sol";
import "./AccessControl.sol";
import "./LiquidTransfer.sol";
contract LiquidRouter is LiquidTransfer, AccessControl, RouterEvents {
address public factoryAddress;
address public immutable chainLinkETH;
uint256 public constant UPDATE_DURATION = 72 hours;
uint80 public constant MAX_ROUND_COUNT = 50;
mapping(address => bool) public registeredPools;
mapping(address => bytes32) public merkleRoot;
mapping(address => string) public merkleIPFS;
mapping(address => bool) public expansionRevoked;
mapping(address => uint256) public chainLinkHeartBeat;
mapping(address => UpdateRoot) public pendingRoots;
mapping(address => ExpandPool) public pendingPools;
struct UpdateRoot {
uint256 updateTime;
bytes32 merkleRoot;
string ipfsAddress;
}
struct ExpandPool {
uint256 updateTime;
address nftAddress;
}
modifier onlyKnownPools(
address _pool
) {
require(
registeredPools[_pool] == true,
"LiquidRouter: UNKNOWN_POOL"
);
_;
}
modifier onlyExpandable(
address _pool
) {
require(
expansionRevoked[_pool] == false,
"LiquidRouter: NOT_EXPANDABLE"
);
_;
}
constructor(
address _factoryAddress,
address _chainLinkETH
) {
require(
_chainLinkETH > address(0),
"LiquidRouter: EMPTY_ADDRESS"
);
factoryAddress = _factoryAddress;
chainLinkETH = _chainLinkETH;
}
function liquidateNFT(
address _pool,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
{
uint256 auctionPrice = ILiquidPool(_pool).liquidateNFT(
msg.sender,
_nftAddress,
_nftTokenId,
_merkleIndex,
_merklePrice,
_merkleProof
);
_safeTransferFrom(
ILiquidPool(_pool).poolToken(),
msg.sender,
_pool,
auctionPrice
);
emit Liquidated(
_nftAddress,
_nftTokenId,
auctionPrice,
msg.sender,
block.timestamp
);
}
function addLiquidPool(
address _pool
)
external
{
require(
msg.sender == factoryAddress,
"LiquidRouter: NOT_FACTORY"
);
registeredPools[_pool] = true;
_addWorker(
_pool,
multisig
);
emit LiquidPoolRegistered(
_pool,
block.timestamp
);
}
function addMerkleRoot(
address _nftAddress,
bytes32 _merkleRoot,
string memory _ipfsAddress
)
external
onlyMultisig
{
require(
merkleRoot[_nftAddress] == 0,
"LiquidRouter: OVERWRITE_DENIED"
);
_addWorker(
_nftAddress,
msg.sender
);
merkleRoot[_nftAddress] = _merkleRoot;
merkleIPFS[_nftAddress] = _ipfsAddress;
}
function startUpdateRoot(
address _nftAddress,
bytes32 _merkleRoot,
string memory _ipfsAddress
)
external
onlyWiseWorker(_nftAddress)
{
require(
_merkleRoot > 0,
"LiquidRouter: INVALID_ROOT"
);
uint256 unlockTime = block.timestamp
+ UPDATE_DURATION;
pendingRoots[_nftAddress] = UpdateRoot({
updateTime: unlockTime,
merkleRoot: _merkleRoot,
ipfsAddress: _ipfsAddress
});
emit RootAnnounced(
msg.sender,
unlockTime,
_nftAddress,
_merkleRoot,
_ipfsAddress
);
}
function finishUpdateRoot(
address _nftAddress
)
external
{
UpdateRoot memory update = pendingRoots[_nftAddress];
require(
update.updateTime > 0,
"LiquidRouter: INVALID_TIME"
);
require(
block.timestamp > update.updateTime,
"LiquidRouter: TOO_EARLY"
);
merkleRoot[_nftAddress] = update.merkleRoot;
merkleIPFS[_nftAddress] = update.ipfsAddress;
delete pendingRoots[_nftAddress];
emit RootUpdated(
msg.sender,
block.timestamp,
_nftAddress,
update.merkleRoot,
update.ipfsAddress
);
}
function startExpandPool(
address _pool,
address _nftAddress
)
external
onlyExpandable(_pool)
onlyWiseWorker(_pool)
{
require(
merkleRoot[_nftAddress] > 0,
"LiquidRouter: ROOT_NOT_SET"
);
uint256 updateTime = block.timestamp
+ UPDATE_DURATION;
pendingPools[_pool] = ExpandPool({
updateTime: updateTime,
nftAddress: _nftAddress
});
emit UpdateAnnounced(
msg.sender,
updateTime,
_pool,
_nftAddress
);
}
function finishExpandPool(
address _pool
)
external
onlyExpandable(_pool)
{
ExpandPool memory update = pendingPools[_pool];
require(
update.updateTime > 0,
"LiquidRouter: INVALID_TIME"
);
require(
block.timestamp > update.updateTime,
"LiquidRouter: TOO_EARLY"
);
ILiquidPool(_pool).addCollection(
update.nftAddress
);
delete pendingPools[_pool];
emit PoolUpdated(
msg.sender,
block.timestamp,
_pool,
update.nftAddress
);
}
function revokeExpansion(
address _pool
)
external
onlyMultisig
{
expansionRevoked[_pool] = true;
emit ExpansionRevoked(
_pool
);
}
function depositFunds(
uint256 _amount,
address _pool
)
public
onlyKnownPools(_pool)
{
uint256 shares = ILiquidPool(_pool).depositFunds(
_amount,
msg.sender
);
_safeTransferFrom(
ILiquidPool(_pool).poolToken(),
msg.sender,
_pool,
_amount
);
emit FundsDeposited(
_pool,
msg.sender,
_amount,
shares,
block.timestamp
);
}
function withdrawFunds(
uint256 _shares,
address _pool
)
public
onlyKnownPools(_pool)
{
uint256 withdrawAmount = ILiquidPool(_pool).withdrawFunds(
_shares,
msg.sender
);
emit FundsWithdrawn(
_pool,
msg.sender,
withdrawAmount,
_shares,
block.timestamp
);
}
function moveFunds(
uint256 _shares,
address _poolToExit,
address _poolToEnter
)
external
{
require(
ILiquidPool(_poolToExit).poolToken() ==
ILiquidPool(_poolToEnter).poolToken(),
"LiquidRouter: TOKENS_MISMATCH"
);
uint256 amountToDeposit = ILiquidPool(
_poolToExit
).calculateWithdrawAmount(
_shares
);
withdrawFunds(
_shares,
_poolToExit
);
depositFunds(
amountToDeposit,
_poolToEnter
);
}
function borrowFunds(
address _pool,
uint256 _takeAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
onlyKnownPools(_pool)
{
_transferFromNFT(
msg.sender,
_pool,
_nftAddress,
_nftTokenId
);
ILiquidPool(_pool).borrowFunds(
msg.sender,
_takeAmount,
_nftAddress,
_nftTokenId,
_merkleIndex,
_merklePrice,
_merkleProof
);
emit FundsBorrowed(
_pool,
_nftAddress,
_nftTokenId,
_takeAmount,
msg.sender,
block.timestamp
);
}
function borrowMoreFunds(
address _pool,
uint256 _takeAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
onlyKnownPools(_pool)
{
ILiquidPool(_pool).borrowMoreFunds(
msg.sender,
_takeAmount,
_nftAddress,
_nftTokenId,
_merkleIndex,
_merklePrice,
_merkleProof
);
emit MoreFundsBorrowed(
_pool,
_nftAddress,
msg.sender,
_nftTokenId,
_takeAmount,
block.timestamp
);
}
function paybackFunds(
address _pool,
uint256 _payAmount,
address _nftAddress,
uint256 _nftTokenId,
uint256 _merkleIndex,
uint256 _merklePrice,
bytes32[] calldata _merkleProof
)
external
onlyKnownPools(_pool)
{
uint256 transferAmount = ILiquidPool(_pool).paybackFunds(
_payAmount,
_nftAddress,
_nftTokenId,
_merkleIndex,
_merklePrice,
_merkleProof
);
address loanOwner = ILiquidPool(_pool).getLoanOwner(
_nftAddress,
_nftTokenId
);
_safeTransferFrom(
ILiquidPool(_pool).poolToken(),
msg.sender,
_pool,
transferAmount
);
emit FundsReturned(
_pool,
_nftAddress,
loanOwner,
transferAmount,
_nftTokenId,
block.timestamp
);
}
function lockFeeDestination(
address[] calldata _pools
)
external
onlyMultisig
{
for (uint32 i = 0; i < _pools.length; i++) {
ILiquidPool(_pools[i]).lockFeeDestination();
}
}
function changeFeeDestinationAddress(
address[] calldata _pools,
address[] calldata _newFeeDestinationAddress
)
external
onlyMultisig
{
for (uint32 i = 0; i < _pools.length; i++) {
ILiquidPool(_pools[i]).changeFeeDestinationAddress(
_newFeeDestinationAddress[i]
);
emit FeeDestinatoinChanged(
_pools[i],
_newFeeDestinationAddress[i]
);
}
}
function withdrawFees(
address[] calldata _pools,
uint256[] calldata _shares
)
external
{
for (uint32 i = 0; i < _pools.length; i++) {
ILiquidPool(_pools[i]).withdrawFunds(
_shares[i],
address(this)
);
}
}
function removeToken(
address _tokenAddress,
address _depositAddress
)
external
onlyMultisig
{
uint256 tokenBalance = _safeBalance(
_tokenAddress,
address(this)
);
_safeTransfer(
_tokenAddress,
_depositAddress,
tokenBalance
);
}
function getLatestAggregatorRoundId(
address _feed
)
public
view
returns (uint80)
{
( uint80 roundId,
,
,
,
) = IChainLink(_feed).latestRoundData();
return uint64(roundId);
}
function getRoundIdByByteShift(
uint16 _phaseId,
uint80 _aggregatorRoundId
)
public
pure
returns (uint80)
{
return uint80(uint256(_phaseId) << 64 | _aggregatorRoundId);
}
function recalibratePreview(
address _feed
)
public
view
returns (uint256)
{
uint80 latestAggregatorRoundId = getLatestAggregatorRoundId(
_feed
);
uint80 iterationCount = _getIterationCount(
latestAggregatorRoundId
);
if (iterationCount < 2) {
revert("LiquidRouter: SMALL_SAMPLE");
}
uint16 phaseId = IChainLink(_feed).phaseId();
uint256 latestTimestamp = _getRoundTimestamp(
_feed,
phaseId,
latestAggregatorRoundId
);
uint256 currentDiff;
uint256 currentBiggest;
uint256 currentSecondBiggest;
for (uint80 i = 1; i < iterationCount; i++) {
uint256 currentTimestamp = _getRoundTimestamp(
_feed,
phaseId,
latestAggregatorRoundId - i
);
currentDiff = latestTimestamp
- currentTimestamp;
latestTimestamp = currentTimestamp;
if (currentDiff >= currentBiggest) {
currentSecondBiggest = currentBiggest;
currentBiggest = currentDiff;
} else if (currentDiff > currentSecondBiggest && currentDiff < currentBiggest) {
currentSecondBiggest = currentDiff;
}
}
return currentSecondBiggest;
}
function _getIterationCount(
uint80 _latestAggregatorRoundId
)
internal
pure
returns (uint80)
{
return _latestAggregatorRoundId > MAX_ROUND_COUNT
? MAX_ROUND_COUNT
: _latestAggregatorRoundId;
}
function _getRoundTimestamp(
address _feed,
uint16 _phaseId,
uint80 _aggregatorRoundId
)
internal
view
returns (uint256)
{
(
,
,
,
uint256 timestamp,
) = IChainLink(_feed).getRoundData(
getRoundIdByByteShift(
_phaseId,
_aggregatorRoundId
)
);
return timestamp;
}
function recalibrate(
address _feed
)
external
{
chainLinkHeartBeat[_feed] = recalibratePreview(_feed);
}
}
文件 5 的 6:LiquidTransfer.sol
pragma solidity =0.8.17;
contract LiquidTransfer {
function _transferNFT(
address _from,
address _to,
address _tokenAddress,
uint256 _tokenId
)
internal
{
bytes memory data = abi.encodeWithSignature(
"safeTransferFrom(address,address,uint256)",
_from,
_to,
_tokenId
);
(bool success,) = address(_tokenAddress).call(
data
);
require(
success,
"LiquidTransfer: NFT_TRANSFER_FAILED"
);
}
function _transferFromNFT(
address _from,
address _to,
address _tokenAddress,
uint256 _tokenId
)
internal
{
bytes memory data = abi.encodeWithSignature(
"safeTransferFrom(address,address,uint256)",
_from,
_to,
_tokenId
);
(bool success, bytes memory resultData) = address(_tokenAddress).call(
data
);
require(
success,
string(resultData)
);
}
bytes4 constant TRANSFER = bytes4(
keccak256(
bytes(
"transfer(address,uint256)"
)
)
);
bytes4 constant TRANSFER_FROM = bytes4(
keccak256(
bytes(
"transferFrom(address,address,uint256)"
)
)
);
bytes4 private constant BALANCE_OF = bytes4(
keccak256(
bytes(
"balanceOf(address)"
)
)
);
function _safeTransfer(
address _token,
address _to,
uint256 _value
)
internal
{
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(
TRANSFER,
_to,
_value
)
);
require(success && (data.length == 0 || abi.decode(data, (bool))),
"LiquidTransfer: TRANSFER_FAILED"
);
}
function _safeTransferFrom(
address _token,
address _from,
address _to,
uint256 _value
)
internal
{
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(
TRANSFER_FROM,
_from,
_to,
_value
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"LiquidTransfer: TRANSFER_FROM_FAILED"
);
}
function _safeBalance(
address _token,
address _owner
)
internal
returns (uint256)
{
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(
BALANCE_OF,
_owner
)
);
if (success == false) return 0;
return abi.decode(
data,
(uint256)
);
}
event ERC721Received(
address operator,
address from,
uint256 tokenId,
bytes data
);
function onERC721Received(
address _operator,
address _from,
uint256 _tokenId,
bytes calldata _data
)
external
returns (bytes4)
{
emit ERC721Received(
_operator,
_from,
_tokenId,
_data
);
return this.onERC721Received.selector;
}
}
文件 6 的 6:RouterEvents.sol
pragma solidity =0.8.17;
contract RouterEvents {
event FundsDeposited(
address indexed pool,
address indexed user,
uint256 amount,
uint256 shares,
uint256 timestamp
);
event FundsWithdrawn(
address indexed pool,
address indexed user,
uint256 amount,
uint256 shares,
uint256 timestamp
);
event FundsBorrowed(
address indexed pool,
address indexed nftAddress,
uint256 indexed tokenId,
uint256 amount,
address borrower,
uint256 timestamp
);
event MoreFundsBorrowed(
address indexed pool,
address indexed nftAddress,
address indexed borrower,
uint256 tokenId,
uint256 amount,
uint256 timestamp
);
event FundsReturned(
address indexed pool,
address indexed nftAddress,
address indexed tokenOwner,
uint256 transferAmount,
uint256 tokenId,
uint256 timestamp
);
event LiquidPoolRegistered(
address indexed pool,
uint256 timestamp
);
event Liquidated(
address indexed nftAddress,
uint256 indexed tokenId,
uint256 discountAmount,
address indexed liquidator,
uint256 timestamp
);
event RootAnnounced(
address caller,
uint256 unlockTime,
address indexed nftAddress,
bytes32 indexed merkleRoot,
string indexed ipfsAddress
);
event RootUpdated(
address caller,
uint256 updateTime,
address indexed nftAddress,
bytes32 indexed merkleRoot,
string indexed ipfsAddress
);
event UpdateAnnounced(
address caller,
uint256 unlockTime,
address indexed pool,
address indexed nftAddress
);
event PoolUpdated(
address caller,
uint256 updateTime,
address indexed pool,
address indexed nftAddress
);
event FeeDestinatoinChanged(
address indexed pool,
address indexed newDestination
);
event ExpansionRevoked(
address pool
);
}
{
"compilationTarget": {
"LiquidRouter.sol": "LiquidRouter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_factoryAddress","type":"address"},{"internalType":"address","name":"_chainLinkETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ERC721Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"ExpansionRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"newDestination","type":"address"}],"name":"FeeDestinatoinChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FundsBorrowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FundsDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"transferAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FundsReturned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LiquidPoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"discountAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Liquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MoreFundsBorrowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newMultisig","type":"address"}],"name":"MultisigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"updateTime","type":"uint256"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"}],"name":"PoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":true,"internalType":"string","name":"ipfsAddress","type":"string"}],"name":"RootAnnounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"updateTime","type":"uint256"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":true,"internalType":"string","name":"ipfsAddress","type":"string"}],"name":"RootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"}],"name":"UpdateAnnounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wiseGroup","type":"address"},{"indexed":false,"internalType":"address","name":"newWorker","type":"address"}],"name":"WorkerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wiseGroup","type":"address"},{"indexed":false,"internalType":"address","name":"existingWorker","type":"address"}],"name":"WorkerRemoved","type":"event"},{"inputs":[],"name":"MAX_ROUND_COUNT","outputs":[{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPDATE_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"addLiquidPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"string","name":"_ipfsAddress","type":"string"}],"name":"addMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_group","type":"address"},{"internalType":"address","name":"_worker","type":"address"}],"name":"addWorker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_takeAmount","type":"uint256"},{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"},{"internalType":"uint256","name":"_merkleIndex","type":"uint256"},{"internalType":"uint256","name":"_merklePrice","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"borrowFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_takeAmount","type":"uint256"},{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"},{"internalType":"uint256","name":"_merkleIndex","type":"uint256"},{"internalType":"uint256","name":"_merklePrice","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"borrowMoreFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainLinkETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"chainLinkHeartBeat","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"},{"internalType":"address[]","name":"_newFeeDestinationAddress","type":"address[]"}],"name":"changeFeeDestinationAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_pool","type":"address"}],"name":"depositFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"expansionRevoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"finishExpandPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"}],"name":"finishUpdateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feed","type":"address"}],"name":"getLatestAggregatorRoundId","outputs":[{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_phaseId","type":"uint16"},{"internalType":"uint80","name":"_aggregatorRoundId","type":"uint80"}],"name":"getRoundIdByByteShift","outputs":[{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"},{"internalType":"uint256","name":"_merkleIndex","type":"uint256"},{"internalType":"uint256","name":"_merklePrice","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"liquidateNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"}],"name":"lockFeeDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"merkleIPFS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_poolToExit","type":"address"},{"internalType":"address","name":"_poolToEnter","type":"address"}],"name":"moveFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"multisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_payAmount","type":"uint256"},{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"},{"internalType":"uint256","name":"_merkleIndex","type":"uint256"},{"internalType":"uint256","name":"_merklePrice","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"paybackFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingPools","outputs":[{"internalType":"uint256","name":"updateTime","type":"uint256"},{"internalType":"address","name":"nftAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingRoots","outputs":[{"internalType":"uint256","name":"updateTime","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"string","name":"ipfsAddress","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feed","type":"address"}],"name":"recalibrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feed","type":"address"}],"name":"recalibratePreview","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"registeredPools","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_depositAddress","type":"address"}],"name":"removeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_group","type":"address"},{"internalType":"address","name":"_worker","type":"address"}],"name":"removeWorker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"revokeExpansion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_nftAddress","type":"address"}],"name":"startExpandPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"string","name":"_ipfsAddress","type":"string"}],"name":"startUpdateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMultisig","type":"address"}],"name":"updateMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"},{"internalType":"uint256[]","name":"_shares","type":"uint256[]"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_pool","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"workers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]