2024-02-09 21:22:41 +00:00
|
|
|
//SPDX-License-Identifier: MIT
|
|
|
|
pragma solidity ^0.8.2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @title Fluid.
|
|
|
|
* @dev Lending & Borrowing.
|
|
|
|
*/
|
|
|
|
|
2024-05-23 14:33:34 +00:00
|
|
|
import {Basic} from "../../common/basic.sol";
|
2024-02-09 21:22:41 +00:00
|
|
|
import {TokenInterface} from "../../common/interfaces.sol";
|
2024-05-23 14:33:34 +00:00
|
|
|
|
2024-02-09 21:22:41 +00:00
|
|
|
import {Events} from "./events.sol";
|
|
|
|
import {IVault} from "./interface.sol";
|
|
|
|
|
2024-05-23 14:33:34 +00:00
|
|
|
abstract contract FluidConnector is Events, Basic {
|
2024-02-09 21:22:41 +00:00
|
|
|
/**
|
|
|
|
* @dev Returns Eth address
|
|
|
|
*/
|
|
|
|
function getEthAddr() internal pure returns (address) {
|
|
|
|
return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Deposit, borrow, payback and withdraw asset from the vault.
|
|
|
|
* @notice Single function which handles supply, withdraw, borrow & payback
|
|
|
|
* @param vaultAddress_ Vault address.
|
|
|
|
* @param nftId_ NFT ID for interaction. If 0 then create new NFT/position.
|
|
|
|
* @param newCol_ New collateral. If positive then deposit, if negative then withdraw, if 0 then do nothing.
|
|
|
|
* For max deposit use type(uint25).max, for max withdraw use type(uint25).min.
|
|
|
|
* @param newDebt_ New debt. If positive then borrow, if negative then payback, if 0 then do nothing
|
|
|
|
* For max payback use type(uint25).min.
|
|
|
|
* @param repayApproveAmt_ In case of max amount for payback, this amount will be approved for spending.
|
|
|
|
* Should always be positive.
|
|
|
|
* @param getIds_ Array of 5 elements to retrieve IDs:
|
|
|
|
* Nft Id, Supply amount, Withdraw amount, Borrow Amount, Payback Amount
|
|
|
|
* @param setIds_ Array of 5 elements to store IDs generated:
|
|
|
|
* Nft Id, Supply amount, Withdraw amount, Borrow Amount, Payback Amount
|
|
|
|
*/
|
2024-02-10 19:12:47 +00:00
|
|
|
function operateWithIds(
|
2024-02-09 21:22:41 +00:00
|
|
|
address vaultAddress_,
|
|
|
|
uint256 nftId_,
|
|
|
|
int256 newCol_,
|
|
|
|
int256 newDebt_,
|
|
|
|
uint256 repayApproveAmt_,
|
|
|
|
uint256[] memory getIds_,
|
|
|
|
uint256[] memory setIds_
|
|
|
|
)
|
|
|
|
external
|
|
|
|
payable
|
|
|
|
returns (string memory _eventName, bytes memory _eventParam)
|
|
|
|
{
|
|
|
|
if (getIds_[1] > 0 && getIds_[2] > 0) {
|
|
|
|
revert("Supply and withdraw get IDs cannot both be > 0.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getIds_[3] > 0 && getIds_[4] > 0) {
|
|
|
|
revert("Borrow and payback get IDs cannot both be > 0.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setIds_[1] > 0 && setIds_[2] > 0) {
|
|
|
|
revert("Supply and withdraw set IDs cannot both be > 0.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setIds_[3] > 0 && setIds_[4] > 0) {
|
|
|
|
revert("Borrow and payback set IDs cannot both be > 0.");
|
|
|
|
}
|
|
|
|
|
|
|
|
nftId_ = getUint(getIds_[0], nftId_);
|
|
|
|
|
|
|
|
newCol_ = getIds_[1] > 0
|
|
|
|
? int256(getUint(getIds_[1], uint256(newCol_)))
|
|
|
|
: getIds_[2] > 0
|
|
|
|
? -int256(getUint(getIds_[2], uint256(newCol_)))
|
|
|
|
: newCol_;
|
|
|
|
|
|
|
|
newDebt_ = getIds_[3] > 0
|
|
|
|
? int256(getUint(getIds_[3], uint256(newDebt_)))
|
|
|
|
: getIds_[4] > 0
|
|
|
|
? -int256(getUint(getIds_[4], uint256(newDebt_)))
|
|
|
|
: newDebt_;
|
|
|
|
|
|
|
|
IVault vault_ = IVault(vaultAddress_);
|
|
|
|
|
|
|
|
IVault.ConstantViews memory vaultDetails_ = vault_.constantsView();
|
|
|
|
|
|
|
|
uint256 ethAmount_;
|
|
|
|
|
|
|
|
bool isColMax_ = newCol_ == type(int256).max;
|
|
|
|
|
|
|
|
// Deposit
|
|
|
|
if (newCol_ > 0) {
|
|
|
|
if (vaultDetails_.supplyToken == getEthAddr()) {
|
|
|
|
ethAmount_ = isColMax_
|
|
|
|
? address(this).balance
|
|
|
|
: uint256(newCol_);
|
2024-02-11 10:33:32 +00:00
|
|
|
|
|
|
|
newCol_ = int256(ethAmount_);
|
2024-02-09 21:22:41 +00:00
|
|
|
} else {
|
|
|
|
if (isColMax_) {
|
|
|
|
newCol_ = int256(
|
|
|
|
TokenInterface(vaultDetails_.supplyToken).balanceOf(
|
|
|
|
address(this)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:33:34 +00:00
|
|
|
approve(
|
|
|
|
TokenInterface(vaultDetails_.supplyToken),
|
|
|
|
vaultAddress_,
|
2024-02-09 21:22:41 +00:00
|
|
|
uint256(newCol_)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-11 10:33:32 +00:00
|
|
|
bool isPaybackMin_ = newDebt_ == type(int256).min;
|
2024-02-09 21:22:41 +00:00
|
|
|
|
|
|
|
// Payback
|
|
|
|
if (newDebt_ < 0) {
|
|
|
|
if (vaultDetails_.borrowToken == getEthAddr()) {
|
|
|
|
// Needs to be positive as it will be send in msg.value
|
2024-02-11 10:33:32 +00:00
|
|
|
ethAmount_ = isPaybackMin_
|
2024-02-09 21:22:41 +00:00
|
|
|
? repayApproveAmt_
|
2024-02-11 10:33:32 +00:00
|
|
|
: uint256(-newDebt_);
|
2024-02-09 21:22:41 +00:00
|
|
|
} else {
|
2024-02-11 10:33:32 +00:00
|
|
|
isPaybackMin_
|
2024-05-23 14:33:34 +00:00
|
|
|
? approve(
|
|
|
|
TokenInterface(vaultDetails_.borrowToken),
|
|
|
|
vaultAddress_,
|
2024-02-09 21:22:41 +00:00
|
|
|
repayApproveAmt_
|
|
|
|
)
|
2024-05-23 14:33:34 +00:00
|
|
|
: approve(
|
|
|
|
TokenInterface(vaultDetails_.borrowToken),
|
|
|
|
vaultAddress_,
|
2024-02-11 10:33:32 +00:00
|
|
|
uint256(-newDebt_)
|
2024-02-09 21:22:41 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note max withdraw will be handled by Fluid contract
|
|
|
|
(nftId_, newCol_, newDebt_) = vault_.operate{value: ethAmount_}(
|
|
|
|
nftId_,
|
|
|
|
newCol_,
|
|
|
|
newDebt_,
|
|
|
|
address(this)
|
|
|
|
);
|
|
|
|
|
|
|
|
setUint(setIds_[0], nftId_);
|
|
|
|
|
|
|
|
setIds_[1] > 0
|
|
|
|
? setUint(setIds_[1], uint256(newCol_))
|
|
|
|
: setUint(setIds_[2], uint256(newCol_)); // If setIds_[2] != 0, it will set the ID.
|
|
|
|
setIds_[3] > 0
|
|
|
|
? setUint(setIds_[3], uint256(newDebt_))
|
|
|
|
: setUint(setIds_[4], uint256(newDebt_)); // If setIds_[4] != 0, it will set the ID.
|
|
|
|
|
|
|
|
_eventName = "LogOperateWithIds(address,uint256,int256,int256,uint256[],uint256[])";
|
|
|
|
_eventParam = abi.encode(
|
|
|
|
vaultAddress_,
|
|
|
|
nftId_,
|
|
|
|
newCol_,
|
|
|
|
newDebt_,
|
|
|
|
getIds_,
|
|
|
|
setIds_
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Deposit, borrow, payback and withdraw asset from the vault.
|
|
|
|
* @notice Single function which handles supply, withdraw, borrow & payback
|
|
|
|
* @param vaultAddress_ Vault address.
|
|
|
|
* @param nftId_ NFT ID for interaction. If 0 then create new NFT/position.
|
|
|
|
* @param newCol_ New collateral. If positive then deposit, if negative then withdraw, if 0 then do nothing.
|
|
|
|
* For max deposit use type(uint25).max, for max withdraw use type(uint25).min.
|
|
|
|
* @param newDebt_ New debt. If positive then borrow, if negative then payback, if 0 then do nothing
|
|
|
|
* For max payback use type(uint25).min.
|
|
|
|
* @param repayApproveAmt_ In case of max amount for payback, this amount will be approved for spending.
|
|
|
|
* Should always be positive.
|
|
|
|
*/
|
2024-02-10 19:12:47 +00:00
|
|
|
function operate(
|
2024-02-09 21:22:41 +00:00
|
|
|
address vaultAddress_,
|
|
|
|
uint256 nftId_,
|
|
|
|
int256 newCol_,
|
|
|
|
int256 newDebt_,
|
|
|
|
uint256 repayApproveAmt_
|
|
|
|
)
|
|
|
|
external
|
|
|
|
payable
|
|
|
|
returns (string memory _eventName, bytes memory _eventParam)
|
|
|
|
{
|
|
|
|
IVault vault_ = IVault(vaultAddress_);
|
|
|
|
|
|
|
|
IVault.ConstantViews memory vaultDetails_ = vault_.constantsView();
|
|
|
|
|
|
|
|
uint256 ethAmount_;
|
|
|
|
|
|
|
|
bool isColMax_ = newCol_ == type(int256).max;
|
|
|
|
|
|
|
|
// Deposit
|
|
|
|
if (newCol_ > 0) {
|
|
|
|
if (vaultDetails_.supplyToken == getEthAddr()) {
|
|
|
|
ethAmount_ = isColMax_
|
|
|
|
? address(this).balance
|
|
|
|
: uint256(newCol_);
|
2024-02-11 21:02:33 +00:00
|
|
|
|
|
|
|
newCol_ = int256(ethAmount_);
|
2024-02-09 21:22:41 +00:00
|
|
|
} else {
|
|
|
|
if (isColMax_) {
|
|
|
|
newCol_ = int256(
|
|
|
|
TokenInterface(vaultDetails_.supplyToken).balanceOf(
|
|
|
|
address(this)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:33:34 +00:00
|
|
|
approve(
|
|
|
|
TokenInterface(vaultDetails_.supplyToken),
|
|
|
|
vaultAddress_,
|
2024-02-09 21:22:41 +00:00
|
|
|
uint256(newCol_)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-11 10:33:32 +00:00
|
|
|
bool isPaybackMin_ = newDebt_ == type(int256).min;
|
2024-02-09 21:22:41 +00:00
|
|
|
|
|
|
|
// Payback
|
|
|
|
if (newDebt_ < 0) {
|
|
|
|
if (vaultDetails_.borrowToken == getEthAddr()) {
|
|
|
|
// Needs to be positive as it will be send in msg.value
|
2024-02-11 10:33:32 +00:00
|
|
|
ethAmount_ = isPaybackMin_
|
2024-02-09 21:22:41 +00:00
|
|
|
? repayApproveAmt_
|
2024-02-11 10:33:32 +00:00
|
|
|
: uint256(-newDebt_);
|
2024-02-09 21:22:41 +00:00
|
|
|
} else {
|
2024-02-11 10:33:32 +00:00
|
|
|
isPaybackMin_
|
2024-05-23 14:33:34 +00:00
|
|
|
? approve(
|
|
|
|
TokenInterface(vaultDetails_.borrowToken),
|
|
|
|
vaultAddress_,
|
2024-02-09 21:22:41 +00:00
|
|
|
repayApproveAmt_
|
|
|
|
)
|
2024-05-23 14:33:34 +00:00
|
|
|
: approve(
|
|
|
|
TokenInterface(vaultDetails_.borrowToken),
|
|
|
|
vaultAddress_,
|
2024-02-11 10:33:32 +00:00
|
|
|
uint256(-newDebt_)
|
2024-02-09 21:22:41 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note max withdraw will be handled by Fluid contract
|
|
|
|
(nftId_, newCol_, newDebt_) = vault_.operate{value: ethAmount_}(
|
|
|
|
nftId_,
|
|
|
|
newCol_,
|
|
|
|
newDebt_,
|
|
|
|
address(this)
|
|
|
|
);
|
|
|
|
|
|
|
|
_eventName = "LogOperate(address,uint256,int256,int256)";
|
|
|
|
_eventParam = abi.encode(
|
|
|
|
vaultAddress_,
|
|
|
|
nftId_,
|
|
|
|
newCol_,
|
|
|
|
newDebt_
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
contract ConnectV2Fluid is FluidConnector {
|
2024-05-23 14:35:36 +00:00
|
|
|
string public constant name = "Fluid-v1.2";
|
2024-02-09 21:22:41 +00:00
|
|
|
}
|