mirror of
https://github.com/Instadapp/dsa-connectors-2.0.git
synced 2024-07-29 21:57:39 +00:00
Merge pull request #19 from Instadapp/fluid-arbitrum-connectors
Add fluid connectors on arbitrum
This commit is contained in:
commit
98d29e8229
28
contracts/arbitrum/connectors/fluid-staking/events.sol
Normal file
28
contracts/arbitrum/connectors/fluid-staking/events.sol
Normal file
|
@ -0,0 +1,28 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
contract Events {
|
||||
|
||||
event LogDeposit(
|
||||
address indexed stakingPool,
|
||||
uint256 amount,
|
||||
uint getId,
|
||||
uint setId
|
||||
);
|
||||
|
||||
event LogWithdrawAndClaimedReward(
|
||||
address indexed stakingPool,
|
||||
uint256 amount,
|
||||
uint256 rewardAmt,
|
||||
uint getId,
|
||||
uint setIdAmount,
|
||||
uint setIdReward
|
||||
);
|
||||
|
||||
event LogClaimedReward(
|
||||
address indexed stakingPool,
|
||||
address indexed rewardToken,
|
||||
uint256 rewardAmt,
|
||||
uint setId
|
||||
);
|
||||
}
|
13
contracts/arbitrum/connectors/fluid-staking/interface.sol
Normal file
13
contracts/arbitrum/connectors/fluid-staking/interface.sol
Normal file
|
@ -0,0 +1,13 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
interface IStakingRewards {
|
||||
function stake(uint256 amount) external;
|
||||
function withdraw(uint256 amount) external;
|
||||
function getReward() external;
|
||||
function balanceOf(address account) external view returns(uint256);
|
||||
function rewardsToken() external view returns (IERC20);
|
||||
function stakingToken() external view returns (IERC20);
|
||||
}
|
116
contracts/arbitrum/connectors/fluid-staking/main.sol
Normal file
116
contracts/arbitrum/connectors/fluid-staking/main.sol
Normal file
|
@ -0,0 +1,116 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
/**
|
||||
* @title Fluid Staking.
|
||||
* @dev Stake Fluid for earning rewards.
|
||||
*/
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import { Events } from "./events.sol";
|
||||
import { IStakingRewards } from "./interface.sol";
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
contract Main is Basic, Events {
|
||||
|
||||
/**
|
||||
* @dev Deposit ERC20.
|
||||
* @notice Deposit Tokens to staking pool.
|
||||
* @param stakingPool staking pool address.
|
||||
* @param amt staking token amount.
|
||||
* @param getId ID to retrieve amount.
|
||||
* @param setId ID stores the amount of staked tokens.
|
||||
*/
|
||||
function deposit(
|
||||
address stakingPool,
|
||||
uint amt,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint _amt = getUint(getId, amt);
|
||||
|
||||
IStakingRewards stakingContract = IStakingRewards(stakingPool);
|
||||
IERC20 stakingTokenContract = stakingContract.stakingToken();
|
||||
|
||||
_amt = _amt == type(uint256).max
|
||||
? stakingTokenContract.balanceOf(address(this))
|
||||
: _amt;
|
||||
|
||||
approve(TokenInterface(address(stakingTokenContract)), address(stakingContract), _amt);
|
||||
stakingContract.stake(_amt);
|
||||
|
||||
setUint(setId, _amt);
|
||||
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(stakingPool, _amt, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw ERC20.
|
||||
* @notice Withdraw Tokens from the staking pool.
|
||||
* @param stakingPool staking pool address.
|
||||
* @param amt staking token amount.
|
||||
* @param getId ID to retrieve amount.
|
||||
* @param setIdAmount ID stores the amount of stake tokens withdrawn.
|
||||
* @param setIdReward ID stores the amount of reward tokens claimed.
|
||||
*/
|
||||
function withdraw(
|
||||
address stakingPool,
|
||||
uint amt,
|
||||
uint getId,
|
||||
uint setIdAmount,
|
||||
uint setIdReward
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint _amt = getUint(getId, amt);
|
||||
|
||||
IStakingRewards stakingContract = IStakingRewards(stakingPool);
|
||||
IERC20 rewardsToken = stakingContract.rewardsToken();
|
||||
|
||||
_amt = _amt == type(uint256).max
|
||||
? stakingContract.balanceOf(address(this))
|
||||
: _amt;
|
||||
|
||||
uint intialBal = rewardsToken.balanceOf(address(this));
|
||||
stakingContract.withdraw(_amt);
|
||||
stakingContract.getReward();
|
||||
|
||||
uint rewardAmt = rewardsToken.balanceOf(address(this)) - intialBal;
|
||||
|
||||
setUint(setIdAmount, _amt);
|
||||
setUint(setIdReward, rewardAmt);
|
||||
{
|
||||
_eventName = "LogWithdrawAndClaimedReward(address,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(stakingPool, _amt, rewardAmt, getId, setIdAmount, setIdReward);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Claim Reward.
|
||||
* @notice Claim Pending Rewards of tokens staked.
|
||||
* @param stakingPool staking pool address.
|
||||
* @param setId ID stores the amount of reward tokens claimed.
|
||||
*/
|
||||
function claimReward(
|
||||
address stakingPool,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
IStakingRewards stakingContract = IStakingRewards(stakingPool);
|
||||
IERC20 rewardsToken = stakingContract.rewardsToken();
|
||||
|
||||
uint intialBal = rewardsToken.balanceOf(address(this));
|
||||
stakingContract.getReward();
|
||||
uint finalBal = rewardsToken.balanceOf(address(this));
|
||||
|
||||
uint rewardAmt = finalBal - intialBal;
|
||||
|
||||
setUint(setId, rewardAmt);
|
||||
_eventName = "LogClaimedReward(address,address,uint256,uint256)";
|
||||
_eventParam = abi.encode(stakingPool, address(rewardsToken), rewardAmt, setId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
contract ConnectV2StakeFluidArbitrum is Main {
|
||||
string public constant name = "Stake-Fluid-v1.0";
|
||||
}
|
20
contracts/arbitrum/connectors/fluid/events.sol
Normal file
20
contracts/arbitrum/connectors/fluid/events.sol
Normal file
|
@ -0,0 +1,20 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
contract Events {
|
||||
event LogOperate(
|
||||
address vaultAddress,
|
||||
uint256 nftId,
|
||||
int256 newCol,
|
||||
int256 newDebt
|
||||
);
|
||||
|
||||
event LogOperateWithIds(
|
||||
address vaultAddress,
|
||||
uint256 nftId,
|
||||
int256 newCol,
|
||||
int256 newDebt,
|
||||
uint256[] getIds,
|
||||
uint256[] setIds
|
||||
);
|
||||
}
|
47
contracts/arbitrum/connectors/fluid/interface.sol
Normal file
47
contracts/arbitrum/connectors/fluid/interface.sol
Normal file
|
@ -0,0 +1,47 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
interface IVault {
|
||||
/// @dev Single function which handles supply, withdraw, borrow & payback
|
||||
/// @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 nohing
|
||||
/// @param newDebt_ new debt. If positive then borrow, if negative then payback, if 0 then do nohing
|
||||
/// @param to_ address where withdraw or borrow should go. If address(0) then msg.sender
|
||||
/// @return nftId_ if 0 then this returns the newly created NFT Id else returns the same NFT ID
|
||||
/// @return final supply amount. Mainly if max withdraw using type(int).min then this is useful to get perfect amount else remain same as newCol_
|
||||
/// @return final borrow amount. Mainly if max payback using type(int).min then this is useful to get perfect amount else remain same as newDebt_
|
||||
function operate(
|
||||
uint256 nftId_, // if 0 then new position
|
||||
int256 newCol_, // if negative then withdraw
|
||||
int256 newDebt_, // if negative then payback
|
||||
address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (
|
||||
uint256, // nftId_
|
||||
int256, // final supply amount if - then withdraw
|
||||
int256 // final borrow amount if - then payback
|
||||
);
|
||||
|
||||
struct ConstantViews {
|
||||
address liquidity;
|
||||
address factory;
|
||||
address adminImplementation;
|
||||
address secondaryImplementation;
|
||||
address supplyToken;
|
||||
address borrowToken;
|
||||
uint8 supplyDecimals;
|
||||
uint8 borrowDecimals;
|
||||
uint vaultId;
|
||||
bytes32 liquiditySupplyExchangePriceSlot;
|
||||
bytes32 liquidityBorrowExchangePriceSlot;
|
||||
bytes32 liquidityUserSupplySlot;
|
||||
bytes32 liquidityUserBorrowSlot;
|
||||
}
|
||||
|
||||
function constantsView()
|
||||
external
|
||||
view
|
||||
returns (ConstantViews memory constantsView_);
|
||||
}
|
267
contracts/arbitrum/connectors/fluid/main.sol
Normal file
267
contracts/arbitrum/connectors/fluid/main.sol
Normal file
|
@ -0,0 +1,267 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
|
||||
/**
|
||||
* @title Fluid.
|
||||
* @dev Lending & Borrowing.
|
||||
*/
|
||||
|
||||
import {Basic} from "../../common/basic.sol";
|
||||
import {TokenInterface} from "../../common/interfaces.sol";
|
||||
|
||||
import {Events} from "./events.sol";
|
||||
import {IVault} from "./interface.sol";
|
||||
|
||||
abstract contract FluidConnector is Events, Basic {
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
function operateWithIds(
|
||||
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_);
|
||||
|
||||
newCol_ = int256(ethAmount_);
|
||||
} else {
|
||||
if (isColMax_) {
|
||||
newCol_ = int256(
|
||||
TokenInterface(vaultDetails_.supplyToken).balanceOf(
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
approve(
|
||||
TokenInterface(vaultDetails_.supplyToken),
|
||||
vaultAddress_,
|
||||
uint256(newCol_)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool isPaybackMin_ = newDebt_ == type(int256).min;
|
||||
|
||||
// Payback
|
||||
if (newDebt_ < 0) {
|
||||
if (vaultDetails_.borrowToken == getEthAddr()) {
|
||||
// Needs to be positive as it will be send in msg.value
|
||||
ethAmount_ = isPaybackMin_
|
||||
? repayApproveAmt_
|
||||
: uint256(-newDebt_);
|
||||
} else {
|
||||
isPaybackMin_
|
||||
? approve(
|
||||
TokenInterface(vaultDetails_.borrowToken),
|
||||
vaultAddress_,
|
||||
repayApproveAmt_
|
||||
)
|
||||
: approve(
|
||||
TokenInterface(vaultDetails_.borrowToken),
|
||||
vaultAddress_,
|
||||
uint256(-newDebt_)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
function operate(
|
||||
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_);
|
||||
|
||||
newCol_ = int256(ethAmount_);
|
||||
} else {
|
||||
if (isColMax_) {
|
||||
newCol_ = int256(
|
||||
TokenInterface(vaultDetails_.supplyToken).balanceOf(
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
approve(
|
||||
TokenInterface(vaultDetails_.supplyToken),
|
||||
vaultAddress_,
|
||||
uint256(newCol_)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool isPaybackMin_ = newDebt_ == type(int256).min;
|
||||
|
||||
// Payback
|
||||
if (newDebt_ < 0) {
|
||||
if (vaultDetails_.borrowToken == getEthAddr()) {
|
||||
// Needs to be positive as it will be send in msg.value
|
||||
ethAmount_ = isPaybackMin_
|
||||
? repayApproveAmt_
|
||||
: uint256(-newDebt_);
|
||||
} else {
|
||||
isPaybackMin_
|
||||
? approve(
|
||||
TokenInterface(vaultDetails_.borrowToken),
|
||||
vaultAddress_,
|
||||
repayApproveAmt_
|
||||
)
|
||||
: approve(
|
||||
TokenInterface(vaultDetails_.borrowToken),
|
||||
vaultAddress_,
|
||||
uint256(-newDebt_)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ConnectV2FluidArbitrum is FluidConnector {
|
||||
string public constant name = "Fluid-v1.0";
|
||||
}
|
Loading…
Reference in New Issue
Block a user