mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Adding tested contracts
This commit is contained in:
parent
0cf73a7258
commit
6de0228439
26
contracts/mainnet/connectors/notional/SafeInt256.sol
Normal file
26
contracts/mainnet/connectors/notional/SafeInt256.sol
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
|
library SafeInt256 {
|
||||||
|
int256 private constant _INT256_MIN = type(int256).min;
|
||||||
|
|
||||||
|
function mul(int256 a, int256 b) internal pure returns (int256 c) {
|
||||||
|
c = a * b;
|
||||||
|
if (a == -1) require(b == 0 || c / b == a);
|
||||||
|
else require(a == 0 || c / a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function div(int256 a, int256 b) internal pure returns (int256 c) {
|
||||||
|
require(!(b == -1 && a == _INT256_MIN)); // dev: int256 div overflow
|
||||||
|
// NOTE: solidity will automatically revert on divide by zero
|
||||||
|
c = a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sub(int256 x, int256 y) internal pure returns (int256 z) {
|
||||||
|
// taken from uniswap v3
|
||||||
|
require((z = x - y) <= x == (y >= 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function neg(int256 x) internal pure returns (int256 y) {
|
||||||
|
return mul(-1, x);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,95 @@
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
contract Events {
|
contract Events {
|
||||||
|
event LogDepositCollateral(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool isUnderlying,
|
||||||
|
uint256 depositAmount,
|
||||||
|
uint256 assetCashDeposited
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdrawCollateral(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool isUnderlying,
|
||||||
|
uint256 amountWithdrawn
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogClaimNOTE(address indexed account, uint256 notesClaimed);
|
||||||
|
|
||||||
|
event LogRedeemNTokenRaw(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool sellTokenAssets,
|
||||||
|
uint96 tokensToRedeem,
|
||||||
|
int256 assetCashChange
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogRedeemNTokenWithdraw(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
uint96 tokensToRedeem,
|
||||||
|
uint256 amountToWithdraw,
|
||||||
|
bool redeemToUnderlying
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogRedeemNTokenAndDeleverage(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
uint96 tokensToRedeem,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogDepositAndMintNToken(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool isUnderlying,
|
||||||
|
uint256 depositAmount,
|
||||||
|
int256 nTokenBalanceChange
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogMintNTokenFromCash(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
uint256 cashBalanceToMint,
|
||||||
|
int256 nTokenBalanceChange
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogDepositAndLend(
|
||||||
|
address indexed account,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool isUnderlying,
|
||||||
|
uint256 depositAmount,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount,
|
||||||
|
uint32 minLendRate
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogDepositCollateralBorrowAndWithdraw(
|
||||||
|
bool useUnderlying,
|
||||||
|
uint256 depositAmount,
|
||||||
|
uint16 borrowCurrencyId,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount,
|
||||||
|
uint32 maxBorrowRate,
|
||||||
|
bool redeemToUnderlying
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdrawLend(
|
||||||
|
uint16 currencyId,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount,
|
||||||
|
uint32 maxBorrowRate
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogRepayBorrow(
|
||||||
|
uint16 currencyId,
|
||||||
|
uint8 marketIndex,
|
||||||
|
int88 netCashToAccount,
|
||||||
|
uint32 minLendRate
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogBatchActionRaw(address indexed account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
pragma abicoder v2;
|
pragma abicoder v2;
|
||||||
|
|
||||||
import {Token, NotionalInterface} from "./interface.sol";
|
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
|
||||||
|
import {Token, NotionalInterface, BalanceAction, BalanceActionWithTrades} from "./interface.sol";
|
||||||
|
import {SafeInt256} from "./SafeInt256.sol";
|
||||||
import {Basic} from "../../common/basic.sol";
|
import {Basic} from "../../common/basic.sol";
|
||||||
|
import {TokenInterface} from "../../common/interfaces.sol";
|
||||||
|
|
||||||
contract Helpers is Basic {
|
contract Helpers is Basic {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
using SafeInt256 for int256;
|
||||||
uint8 internal constant LEND_TRADE = 0;
|
uint8 internal constant LEND_TRADE = 0;
|
||||||
uint8 internal constant BORROW_TRADE = 1;
|
uint8 internal constant BORROW_TRADE = 1;
|
||||||
int256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
int256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
||||||
uint256 internal constant ETH_CURRENCY_ID = 1;
|
uint256 internal constant ETH_CURRENCY_ID = 1;
|
||||||
int256 private constant _INT256_MIN = type(int256).min;
|
|
||||||
|
|
||||||
NotionalInterface internal constant notional =
|
NotionalInterface internal constant notional =
|
||||||
NotionalInterface(0x1344A36A1B56144C3Bc62E7757377D288fDE0369);
|
NotionalInterface(0x1344A36A1B56144C3Bc62E7757377D288fDE0369);
|
||||||
|
@ -54,7 +58,7 @@ contract Helpers is Basic {
|
||||||
// end of amount and will not result in dust.
|
// end of amount and will not result in dust.
|
||||||
(Token memory assetToken, ) = notional.getCurrency(currencyId);
|
(Token memory assetToken, ) = notional.getCurrency(currencyId);
|
||||||
if (assetToken.decimals == INTERNAL_TOKEN_PRECISION) return amount;
|
if (assetToken.decimals == INTERNAL_TOKEN_PRECISION) return amount;
|
||||||
return div(mul(amount, INTERNAL_TOKEN_PRECISION), assetToken.decimals);
|
return amount.mul(INTERNAL_TOKEN_PRECISION).div(assetToken.decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeLendTrade(
|
function encodeLendTrade(
|
||||||
|
@ -81,24 +85,97 @@ contract Helpers is Basic {
|
||||||
(bytes32(uint256(maxBorrowRate)) << 120);
|
(bytes32(uint256(maxBorrowRate)) << 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mul(int256 a, int256 b) internal pure returns (int256 c) {
|
function getDepositAmountAndSetApproval(
|
||||||
c = a * b;
|
uint256 getId,
|
||||||
if (a == -1) require(b == 0 || c / b == a);
|
uint16 currencyId,
|
||||||
else require(a == 0 || c / a == b);
|
bool useUnderlying,
|
||||||
|
uint256 depositAmount
|
||||||
|
) internal returns (uint256) {
|
||||||
|
depositAmount = getUint(getId, depositAmount);
|
||||||
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying)
|
||||||
|
return
|
||||||
|
depositAmount == uint256(-1)
|
||||||
|
? address(this).balance
|
||||||
|
: depositAmount;
|
||||||
|
|
||||||
|
address tokenAddress = useUnderlying
|
||||||
|
? getUnderlyingToken(currencyId)
|
||||||
|
: getAssetToken(currencyId);
|
||||||
|
if (depositAmount == uint256(-1)) {
|
||||||
|
depositAmount = TokenInterface(tokenAddress).balanceOf(
|
||||||
|
address(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
||||||
|
return depositAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
function div(int256 a, int256 b) internal pure returns (int256 c) {
|
function getBalance(address addr) internal returns (uint256) {
|
||||||
require(!(b == -1 && a == _INT256_MIN)); // dev: int256 div overflow
|
if (addr == ethAddr) {
|
||||||
// NOTE: solidity will automatically revert on divide by zero
|
return address(this).balance;
|
||||||
c = a / b;
|
}
|
||||||
|
|
||||||
|
return TokenInterface(addr).balanceOf(address(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
function sub(int256 x, int256 y) internal pure returns (int256 z) {
|
function getAddress(uint16 currencyId, bool useUnderlying)
|
||||||
// taken from uniswap v3
|
internal
|
||||||
require((z = x - y) <= x == (y >= 0));
|
returns (address)
|
||||||
|
{
|
||||||
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying) {
|
||||||
|
return ethAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
useUnderlying
|
||||||
|
? getUnderlyingToken(currencyId)
|
||||||
|
: getAssetToken(currencyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//function getDepositAmountAndSetApproval(uint16 currencyId) internal;
|
function executeTradeActionWithBalanceChange(
|
||||||
|
BalanceActionWithTrades[] memory action,
|
||||||
|
uint256 msgValue,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool useUnderlying,
|
||||||
|
uint256 setId
|
||||||
|
) internal {
|
||||||
|
address tokenAddress;
|
||||||
|
uint256 balanceBefore;
|
||||||
|
if (setId != 0) {
|
||||||
|
tokenAddress = getAddress(currencyId, useUnderlying);
|
||||||
|
balanceBefore = getBalance(tokenAddress);
|
||||||
|
}
|
||||||
|
|
||||||
//function executeActionWithBalanceChange(uint16 currencyId) internal;
|
notional.batchBalanceAndTradeAction{value: msgValue}(
|
||||||
|
address(this),
|
||||||
|
action
|
||||||
|
);
|
||||||
|
|
||||||
|
if (setId != 0) {
|
||||||
|
uint256 balanceAfter = getBalance(tokenAddress);
|
||||||
|
setUint(setId, balanceAfter.sub(balanceBefore));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeActionWithBalanceChange(
|
||||||
|
BalanceAction[] memory action,
|
||||||
|
uint256 msgValue,
|
||||||
|
uint16 currencyId,
|
||||||
|
bool useUnderlying,
|
||||||
|
uint256 setId
|
||||||
|
) internal {
|
||||||
|
address tokenAddress;
|
||||||
|
uint256 balanceBefore;
|
||||||
|
if (setId != 0) {
|
||||||
|
tokenAddress = getAddress(currencyId, useUnderlying);
|
||||||
|
balanceBefore = getBalance(tokenAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
notional.batchBalanceAction{value: msgValue}(address(this), action);
|
||||||
|
|
||||||
|
if (setId != 0) {
|
||||||
|
uint256 balanceAfter = getBalance(tokenAddress);
|
||||||
|
setUint(setId, balanceAfter.sub(balanceBefore));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,13 @@ interface NotionalInterface {
|
||||||
uint256 lastClaimTime
|
uint256 lastClaimTime
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function getfCashAmountGivenCashAmount(
|
||||||
|
uint16 currencyId,
|
||||||
|
int88 netCashToAccount,
|
||||||
|
uint256 marketIndex,
|
||||||
|
uint256 blockTime
|
||||||
|
) external view returns (int256);
|
||||||
|
|
||||||
function depositUnderlyingToken(
|
function depositUnderlyingToken(
|
||||||
address account,
|
address account,
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
|
@ -120,7 +127,8 @@ interface NotionalInterface {
|
||||||
BalanceAction[] calldata actions
|
BalanceAction[] calldata actions
|
||||||
) external payable;
|
) external payable;
|
||||||
|
|
||||||
function batchBalanceAndTradeAction(address account, BalanceActionWithTrades[] calldata actions)
|
function batchBalanceAndTradeAction(
|
||||||
external
|
address account,
|
||||||
payable;
|
BalanceActionWithTrades[] calldata actions
|
||||||
|
) external payable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
pragma abicoder v2;
|
pragma abicoder v2;
|
||||||
|
|
||||||
import { Helpers } from "./helpers.sol";
|
import {Helpers} from "./helpers.sol";
|
||||||
import { Events } from "./events.sol";
|
import {SafeInt256} from "./SafeInt256.sol";
|
||||||
import { DepositActionType, BalanceActionWithTrades, BalanceAction } from "./interface.sol";
|
import {Events} from "./events.sol";
|
||||||
import { TokenInterface } from "../../common/interfaces.sol";
|
import {DepositActionType, BalanceActionWithTrades, BalanceAction} from "./interface.sol";
|
||||||
|
import {TokenInterface} from "../../common/interfaces.sol";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Notional
|
* @title Notional
|
||||||
* @notice Fixed Rate Lending and Borrowing
|
* @notice Fixed Rate Lending and Borrowing
|
||||||
*/
|
*/
|
||||||
abstract contract NotionalResolver is Events, Helpers {
|
abstract contract NotionalResolver is Events, Helpers {
|
||||||
|
using SafeInt256 for int256;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Deposit collateral into Notional
|
* @notice Deposit collateral into Notional
|
||||||
|
@ -24,29 +26,50 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
function depositCollateral(
|
function depositCollateral(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
bool useUnderlying,
|
bool useUnderlying,
|
||||||
uint depositAmount,
|
uint256 depositAmount,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
)
|
||||||
uint assetCashDeposited;
|
external
|
||||||
address tokenAddress = useUnderlying ? getUnderlyingToken(currencyId) : getAssetToken(currencyId);
|
payable
|
||||||
depositAmount = getUint(getId, depositAmount);
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
if (depositAmount == uint(-1)) depositAmount = TokenInterface(tokenAddress).balanceOf(address(this));
|
{
|
||||||
|
depositAmount = getDepositAmountAndSetApproval(
|
||||||
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
getId,
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 assetCashDeposited;
|
||||||
if (useUnderlying && currencyId == ETH_CURRENCY_ID) {
|
if (useUnderlying && currencyId == ETH_CURRENCY_ID) {
|
||||||
assetCashDeposited = notional.depositUnderlyingToken{value: depositAmount}(address(this), currencyId, depositAmount);
|
assetCashDeposited = notional.depositUnderlyingToken{
|
||||||
|
value: depositAmount
|
||||||
|
}(address(this), currencyId, depositAmount);
|
||||||
} else if (useUnderlying) {
|
} else if (useUnderlying) {
|
||||||
assetCashDeposited = notional.depositUnderlyingToken{value: depositAmount}(address(this), currencyId, depositAmount);
|
assetCashDeposited = notional.depositUnderlyingToken(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
assetCashDeposited = notional.depositAssetToken(address(this), currencyId, depositAmount);
|
assetCashDeposited = notional.depositAssetToken(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUint(setId, assetCashDeposited);
|
setUint(setId, assetCashDeposited);
|
||||||
|
|
||||||
_eventName = "LogDepositCollateral(uint16,bool,uint256,uint256)";
|
_eventName = "LogDepositCollateral(uint16,bool,uint256,uint256)";
|
||||||
_eventParam = abi.encode(address(this), currencyId, useUnderlying, depositAmount, assetCashDeposited);
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount,
|
||||||
|
assetCashDeposited
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,31 +85,42 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
function withdrawCollateral(
|
function withdrawCollateral(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
bool redeemToUnderlying,
|
bool redeemToUnderlying,
|
||||||
uint withdrawAmount,
|
uint256 withdrawAmount,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
withdrawAmount = getUint(getId, withdrawAmount);
|
withdrawAmount = getUint(getId, withdrawAmount);
|
||||||
uint88 amountInternalPrecision = withdrawAmount == uint(-1) ?
|
uint88 amountInternalPrecision = withdrawAmount == uint256(-1)
|
||||||
uint88(getCashBalance(currencyId)) :
|
? uint88(getCashBalance(currencyId))
|
||||||
uint88(convertToInternal(currencyId, int256(withdrawAmount)));
|
: uint88(convertToInternal(currencyId, int256(withdrawAmount)));
|
||||||
|
|
||||||
uint amountWithdrawn = notional.withdraw(currencyId, amountInternalPrecision, redeemToUnderlying);
|
uint256 amountWithdrawn = notional.withdraw(
|
||||||
|
currencyId,
|
||||||
|
amountInternalPrecision,
|
||||||
|
redeemToUnderlying
|
||||||
|
);
|
||||||
// Sets the amount of tokens withdrawn to address(this)
|
// Sets the amount of tokens withdrawn to address(this)
|
||||||
setUint(setId, amountWithdrawn);
|
setUint(setId, amountWithdrawn);
|
||||||
|
|
||||||
_eventName = "LogWithdrawCollateral(address,uint16,bool,uint256)";
|
_eventName = "LogWithdrawCollateral(address,uint16,bool,uint256)";
|
||||||
_eventParam = abi.encode(address(this), currencyId, redeemToUnderlying, amountWithdrawn);
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
redeemToUnderlying,
|
||||||
|
amountWithdrawn
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Claims NOTE tokens and transfers to the address
|
* @dev Claims NOTE tokens and transfers to the address
|
||||||
* @param setId the id to set the balance of NOTE tokens claimed
|
* @param setId the id to set the balance of NOTE tokens claimed
|
||||||
*/
|
*/
|
||||||
function claimNOTE(
|
function claimNOTE(uint256 setId)
|
||||||
uint setId
|
external
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
payable
|
||||||
uint notesClaimed = notional.nTokenClaimIncentives();
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
uint256 notesClaimed = notional.nTokenClaimIncentives();
|
||||||
setUint(setId, notesClaimed);
|
setUint(setId, notesClaimed);
|
||||||
|
|
||||||
_eventName = "LogClaimNOTE(address,uint256)";
|
_eventName = "LogClaimNOTE(address,uint256)";
|
||||||
|
@ -108,21 +142,35 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
bool sellTokenAssets,
|
bool sellTokenAssets,
|
||||||
uint96 tokensToRedeem,
|
uint96 tokensToRedeem,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
tokensToRedeem = uint96(getUint(getId, tokensToRedeem));
|
tokensToRedeem = uint96(getUint(getId, tokensToRedeem));
|
||||||
if (tokensToRedeem == uint96(-1)) tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
if (tokensToRedeem == uint96(-1))
|
||||||
int _assetCashChange = notional.nTokenRedeem(address(this), currencyId, tokensToRedeem, sellTokenAssets);
|
tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
||||||
|
int256 _assetCashChange = notional.nTokenRedeem(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
tokensToRedeem,
|
||||||
|
sellTokenAssets
|
||||||
|
);
|
||||||
|
|
||||||
// Floor asset cash change at zero in order to properly set the uint. If the asset cash change is negative
|
// Floor asset cash change at zero in order to properly set the uint. If the asset cash change is negative
|
||||||
// (this will almost certainly never happen), then no withdraw is possible.
|
// (this will almost certainly never happen), then no withdraw is possible.
|
||||||
uint assetCashChange = _assetCashChange > 0 ? uint(_assetCashChange) : 0;
|
uint256 assetCashChange = _assetCashChange > 0
|
||||||
|
? uint256(_assetCashChange)
|
||||||
|
: 0;
|
||||||
|
|
||||||
setUint(setId, assetCashChange);
|
setUint(setId, assetCashChange);
|
||||||
|
|
||||||
_eventName = "LogRedeemNTokenRaw(address,uint16,bool,uint,uint)";
|
_eventName = "LogRedeemNTokenRaw(address,uint16,bool,uint96,int256)";
|
||||||
_eventParam = abi.encode(address(this), currencyId, sellTokenAssets, tokensToRedeem, assetCashChange);
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
sellTokenAssets,
|
||||||
|
tokensToRedeem,
|
||||||
|
assetCashChange
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,49 +187,43 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
*/
|
*/
|
||||||
function redeemNTokenAndWithdraw(
|
function redeemNTokenAndWithdraw(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint tokensToRedeem,
|
uint96 tokensToRedeem,
|
||||||
uint amountToWithdraw,
|
uint256 amountToWithdraw,
|
||||||
bool redeemToUnderlying,
|
bool redeemToUnderlying,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
tokensToRedeem = getUint(getId, tokensToRedeem);
|
tokensToRedeem = uint96(getUint(getId, uint256(tokensToRedeem)));
|
||||||
if (tokensToRedeem == uint(-1)) tokensToRedeem = uint(getNTokenBalance(currencyId));
|
if (tokensToRedeem == uint96(-1))
|
||||||
|
tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
||||||
|
|
||||||
BalanceAction[] memory action = new BalanceAction[](1);
|
BalanceAction[] memory action = new BalanceAction[](1);
|
||||||
action[0].actionType = DepositActionType.RedeemNToken;
|
action[0].actionType = DepositActionType.RedeemNToken;
|
||||||
action[0].currencyId = currencyId;
|
action[0].currencyId = currencyId;
|
||||||
action[0].depositActionAmount = tokensToRedeem;
|
action[0].depositActionAmount = tokensToRedeem;
|
||||||
action[0].redeemToUnderlying = redeemToUnderlying;
|
action[0].redeemToUnderlying = redeemToUnderlying;
|
||||||
if (amountToWithdraw == uint(-1)) {
|
if (amountToWithdraw == uint256(-1)) {
|
||||||
action[0].withdrawEntireCashBalance = true;
|
action[0].withdrawEntireCashBalance = true;
|
||||||
} else {
|
} else {
|
||||||
action[0].withdrawAmountInternalPrecision = amountToWithdraw;
|
action[0].withdrawAmountInternalPrecision = amountToWithdraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint balanceBefore;
|
executeActionWithBalanceChange(
|
||||||
address tokenAddress;
|
action,
|
||||||
if (setId != 0) {
|
0,
|
||||||
// Only run this if we are going to use the balance change
|
currencyId,
|
||||||
address tokenAddress = redeemToUnderlying ?
|
redeemToUnderlying,
|
||||||
getUnderlyingToken(currencyId) :
|
setId
|
||||||
getAssetToken(currencyId);
|
);
|
||||||
|
|
||||||
// TODO: handle ETH
|
_eventName = "LogRedeemNTokenWithdraw(address,uint16,uint96,uint256,bool)";
|
||||||
balanceBefore = TokenInterface(tokenAddress).balanceOf(address(this));
|
_eventParam = abi.encode(
|
||||||
}
|
address(this),
|
||||||
|
currencyId,
|
||||||
notional.batchBalanceAction(address(this), action);
|
tokensToRedeem,
|
||||||
|
amountToWithdraw,
|
||||||
if (setId != 0) {
|
redeemToUnderlying
|
||||||
// TODO: handle ETH
|
);
|
||||||
uint netBalance = sub(balanceBefore, TokenInterface(tokenAddress).balanceOf(address(this)));
|
|
||||||
// This can be used to determine the exact amount withdrawn
|
|
||||||
setUint(setId, netBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
_eventName = "LogRedeemNTokenWithdraw(address,uint16,uint,uint,bool)";
|
|
||||||
_eventParam = abi.encode(address(this), currencyId, tokensToRedeem, amountToWithdraw, redeemToUnderlying);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,13 +245,15 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
uint8 marketIndex,
|
uint8 marketIndex,
|
||||||
uint88 fCashAmount,
|
uint88 fCashAmount,
|
||||||
uint32 minLendRate,
|
uint32 minLendRate,
|
||||||
uint getId
|
uint256 getId
|
||||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
tokensToRedeem = uint96(getUint(getId, tokensToRedeem));
|
tokensToRedeem = uint96(getUint(getId, tokensToRedeem));
|
||||||
if (tokensToRedeem == uint96(-1)) tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
if (tokensToRedeem == uint96(-1))
|
||||||
notional.nTokenRedeem(address(this), currencyId, tokensToRedeem, true);
|
tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
||||||
|
|
||||||
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](1);
|
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](
|
||||||
|
1
|
||||||
|
);
|
||||||
action[0].actionType = DepositActionType.RedeemNToken;
|
action[0].actionType = DepositActionType.RedeemNToken;
|
||||||
action[0].currencyId = currencyId;
|
action[0].currencyId = currencyId;
|
||||||
action[0].depositActionAmount = tokensToRedeem;
|
action[0].depositActionAmount = tokensToRedeem;
|
||||||
|
@ -221,11 +265,16 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
|
|
||||||
notional.batchBalanceAndTradeAction(address(this), action);
|
notional.batchBalanceAndTradeAction(address(this), action);
|
||||||
|
|
||||||
_eventName = "LogRedeemNTokenAndDeleverage(address,uint16,uint,uint8,uint)";
|
_eventName = "LogRedeemNTokenAndDeleverage(address,uint16,uint96,uint8,uint88)";
|
||||||
_eventParam = abi.encode(address(this), currencyId, tokensToRedeem, marketIndex, fCashAmount);
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
tokensToRedeem,
|
||||||
|
marketIndex,
|
||||||
|
fCashAmount
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Deposit asset or underlying tokens and mint nTokens in a single transaction
|
* @notice Deposit asset or underlying tokens and mint nTokens in a single transaction
|
||||||
* @param currencyId notional defined currency id to deposit
|
* @param currencyId notional defined currency id to deposit
|
||||||
|
@ -237,46 +286,70 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
*/
|
*/
|
||||||
function depositAndMintNToken(
|
function depositAndMintNToken(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint depositAmount,
|
uint256 depositAmount,
|
||||||
bool useUnderlying,
|
bool useUnderlying,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
)
|
||||||
address tokenAddress = useUnderlying ? getUnderlyingToken(currencyId) : getAssetToken(currencyId);
|
external
|
||||||
depositAmount = getUint(getId, depositAmount);
|
payable
|
||||||
if (depositAmount == uint(-1)) depositAmount = TokenInterface(tokenAddress).balanceOf(address(this));
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
depositAmount = getDepositAmountAndSetApproval(
|
||||||
|
getId,
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
|
|
||||||
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
|
||||||
BalanceAction[] memory action = new BalanceAction[](1);
|
BalanceAction[] memory action = new BalanceAction[](1);
|
||||||
action[0].actionType = useUnderlying ? DepositActionType.DepositUnderlyingAndMintNToken : DepositActionType.DepositAssetAndMintNToken;
|
action[0].actionType = useUnderlying
|
||||||
|
? DepositActionType.DepositUnderlyingAndMintNToken
|
||||||
|
: DepositActionType.DepositAssetAndMintNToken;
|
||||||
action[0].currencyId = currencyId;
|
action[0].currencyId = currencyId;
|
||||||
action[0].depositActionAmount = depositAmount;
|
action[0].depositActionAmount = depositAmount;
|
||||||
// withdraw amount, withdraw cash and redeem to underlying are all 0 and false
|
// withdraw amount, withdraw cash and redeem to underlying are all 0 and false
|
||||||
|
|
||||||
int256 nTokenBefore;
|
int256 nTokenBefore = getNTokenBalance(currencyId);
|
||||||
if (setId != 0) {
|
|
||||||
nTokenBefore = getNTokenBalance(currencyId);
|
uint256 msgValue = 0;
|
||||||
}
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying)
|
||||||
|
msgValue = depositAmount;
|
||||||
|
|
||||||
uint msgValue = currencyId == ETH_CURRENCY_ID ? depositAmount : 0;
|
|
||||||
notional.batchBalanceAction{value: msgValue}(address(this), action);
|
notional.batchBalanceAction{value: msgValue}(address(this), action);
|
||||||
|
|
||||||
|
int256 nTokenBalanceChange = getNTokenBalance(currencyId).sub(
|
||||||
|
nTokenBefore
|
||||||
|
);
|
||||||
|
|
||||||
if (setId != 0) {
|
if (setId != 0) {
|
||||||
// Set the amount of nTokens minted
|
// Set the amount of nTokens minted
|
||||||
setUint(setId, uint(sub(getNTokenBalance(currencyId), nTokenBefore)));
|
setUint(setId, uint256(nTokenBalanceChange));
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: events
|
_eventName = "LogDepositAndMintNToken(address,uint16,bool,uint256,int256)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount,
|
||||||
|
nTokenBalanceChange
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mintNTokenFromCash(
|
function mintNTokenFromCash(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint cashBalanceToMint,
|
uint256 cashBalanceToMint,
|
||||||
uint getId,
|
uint256 getId,
|
||||||
uint setId
|
uint256 setId
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
cashBalanceToMint = getUint(getId, cashBalanceToMint);
|
cashBalanceToMint = getUint(getId, cashBalanceToMint);
|
||||||
if (cashBalanceToMint == uint(-1)) cashBalanceToMint = uint(getCashBalance(currencyId));
|
if (cashBalanceToMint == uint256(-1))
|
||||||
|
cashBalanceToMint = uint256(getCashBalance(currencyId));
|
||||||
|
|
||||||
BalanceAction[] memory action = new BalanceAction[](1);
|
BalanceAction[] memory action = new BalanceAction[](1);
|
||||||
action[0].actionType = DepositActionType.ConvertCashToNToken;
|
action[0].actionType = DepositActionType.ConvertCashToNToken;
|
||||||
|
@ -284,73 +357,97 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
action[0].depositActionAmount = cashBalanceToMint;
|
action[0].depositActionAmount = cashBalanceToMint;
|
||||||
// NOTE: withdraw amount, withdraw cash and redeem to underlying are all 0 and false
|
// NOTE: withdraw amount, withdraw cash and redeem to underlying are all 0 and false
|
||||||
|
|
||||||
int256 nTokenBefore;
|
int256 nTokenBefore = getNTokenBalance(currencyId);
|
||||||
if (setId != 0) {
|
|
||||||
nTokenBefore = getNTokenBalance(currencyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
notional.batchBalanceAction(address(this), action);
|
notional.batchBalanceAction(address(this), action);
|
||||||
|
|
||||||
|
int256 nTokenBalanceChange = getNTokenBalance(currencyId).sub(
|
||||||
|
nTokenBefore
|
||||||
|
);
|
||||||
|
|
||||||
if (setId != 0) {
|
if (setId != 0) {
|
||||||
// Set the amount of nTokens minted
|
// Set the amount of nTokens minted
|
||||||
setUint(setId, uint(sub(getNTokenBalance(currencyId), nTokenBefore)));
|
setUint(setId, uint256(nTokenBalanceChange));
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: events
|
_eventName = "LogMintNTokenFromCash(address,uint16,uint256,int256)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
cashBalanceToMint,
|
||||||
|
nTokenBalanceChange
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function depositAndLend(
|
function depositAndLend(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint depositAmount,
|
uint256 depositAmount,
|
||||||
bool useUnderlying,
|
bool useUnderlying,
|
||||||
uint8 marketIndex,
|
uint8 marketIndex,
|
||||||
uint88 fCashAmount,
|
uint88 fCashAmount,
|
||||||
uint32 minLendRate,
|
uint32 minLendRate,
|
||||||
uint getId
|
uint256 getId
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
)
|
||||||
address tokenAddress = useUnderlying ? getUnderlyingToken(currencyId) : getAssetToken(currencyId);
|
external
|
||||||
depositAmount = getUint(getId, depositAmount);
|
payable
|
||||||
if (depositAmount == uint(-1)) depositAmount = TokenInterface(tokenAddress).balanceOf(address(this));
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
depositAmount = getDepositAmountAndSetApproval(
|
||||||
|
getId,
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
|
|
||||||
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](
|
||||||
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](1);
|
1
|
||||||
action[0].actionType = useUnderlying ? DepositActionType.DepositUnderlying : DepositActionType.DepositAsset;
|
);
|
||||||
|
action[0].actionType = useUnderlying
|
||||||
|
? DepositActionType.DepositUnderlying
|
||||||
|
: DepositActionType.DepositAsset;
|
||||||
action[0].currencyId = currencyId;
|
action[0].currencyId = currencyId;
|
||||||
action[0].depositActionAmount = depositAmount;
|
action[0].depositActionAmount = depositAmount;
|
||||||
// Withdraw any residual cash from lending back to the token that was used
|
// Withdraw any residual cash from lending back to the token that was used
|
||||||
action[0].withdrawEntireCashBalance = true;
|
action[0].withdrawEntireCashBalance = true;
|
||||||
// TODO: will redeem underlying work with ETH?
|
|
||||||
action[0].redeemToUnderlying = useUnderlying;
|
action[0].redeemToUnderlying = useUnderlying;
|
||||||
|
|
||||||
bytes32[] memory trades = new bytes32[](1);
|
bytes32[] memory trades = new bytes32[](1);
|
||||||
trades[0] = encodeLendTrade(marketIndex, fCashAmount, minLendRate);
|
trades[0] = encodeLendTrade(marketIndex, fCashAmount, minLendRate);
|
||||||
action[0].trades = trades;
|
action[0].trades = trades;
|
||||||
|
|
||||||
uint msgValue = currencyId == ETH_CURRENCY_ID ? depositAmount : 0;
|
uint256 msgValue = 0;
|
||||||
notional.batchBalanceAndTradeAction{value: msgValue}(address(this), action);
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying)
|
||||||
|
msgValue = depositAmount;
|
||||||
|
|
||||||
// todo: events
|
notional.batchBalanceAndTradeAction{value: msgValue}(
|
||||||
|
address(this),
|
||||||
|
action
|
||||||
|
);
|
||||||
|
|
||||||
|
_eventName = "LogDepositAndLend(address,uint16,bool,uint256,uint8,uint88,uint32)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount,
|
||||||
|
marketIndex,
|
||||||
|
fCashAmount,
|
||||||
|
minLendRate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function depositCollateralBorrowAndWithdraw(
|
function getDepositCollateralBorrowAndWithdrawActions(
|
||||||
uint16 depositCurrencyId,
|
uint16 depositCurrencyId,
|
||||||
bool useUnderlying,
|
bool useUnderlying,
|
||||||
uint depositAmount,
|
uint256 depositAmount,
|
||||||
uint16 borrowCurrencyId,
|
uint16 borrowCurrencyId,
|
||||||
uint8 marketIndex,
|
uint8 marketIndex,
|
||||||
uint88 fCashAmount,
|
uint88 fCashAmount,
|
||||||
uint32 maxBorrowRate,
|
uint32 maxBorrowRate,
|
||||||
bool redeemToUnderlying,
|
bool redeemToUnderlying
|
||||||
uint getId,
|
) internal returns (BalanceActionWithTrades[] memory action) {
|
||||||
uint setId
|
BalanceActionWithTrades[]
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
memory actions = new BalanceActionWithTrades[](2);
|
||||||
require(depositCurrencyId != borrowCurrencyId);
|
|
||||||
address tokenAddress = useUnderlying ? getUnderlyingToken(depositCurrencyId) : getAssetToken(depositCurrencyId);
|
|
||||||
depositAmount = getUint(getId, depositAmount);
|
|
||||||
if (depositAmount == uint(-1)) depositAmount = TokenInterface(tokenAddress).balanceOf(address(this));
|
|
||||||
|
|
||||||
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
|
||||||
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](2);
|
|
||||||
|
|
||||||
uint256 depositIndex;
|
uint256 depositIndex;
|
||||||
uint256 borrowIndex;
|
uint256 borrowIndex;
|
||||||
|
@ -362,36 +459,85 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
borrowIndex = 0;
|
borrowIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
action[depositIndex].actionType = useUnderlying ? DepositActionType.DepositUnderlying : DepositActionType.DepositAsset;
|
actions[depositIndex].actionType = useUnderlying
|
||||||
action[depositIndex].currencyId = depositCurrencyId;
|
? DepositActionType.DepositUnderlying
|
||||||
action[depositIndex].depositActionAmount = depositAmount;
|
: DepositActionType.DepositAsset;
|
||||||
uint msgValue = depositCurrencyId == ETH_CURRENCY_ID ? depositAmount : 0;
|
actions[depositIndex].currencyId = depositCurrencyId;
|
||||||
|
actions[depositIndex].depositActionAmount = depositAmount;
|
||||||
|
|
||||||
action[borrowIndex].actionType = DepositActionType.None;
|
actions[borrowIndex].actionType = DepositActionType.None;
|
||||||
action[borrowIndex].currencyId = borrowCurrencyId;
|
actions[borrowIndex].currencyId = borrowCurrencyId;
|
||||||
// Withdraw borrowed amount to wallet
|
// Withdraw borrowed amount to wallet
|
||||||
action[borrowIndex].withdrawEntireCashBalance = true;
|
actions[borrowIndex].withdrawEntireCashBalance = true;
|
||||||
// TODO: will redeem underlying work with ETH?
|
actions[borrowIndex].redeemToUnderlying = redeemToUnderlying;
|
||||||
action[borrowIndex].redeemToUnderlying = useUnderlying;
|
|
||||||
|
|
||||||
bytes32[] memory trades = new bytes32[](1);
|
bytes32[] memory trades = new bytes32[](1);
|
||||||
trades[borrowIndex] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
||||||
action[borrowIndex].trades = trades;
|
actions[borrowIndex].trades = trades;
|
||||||
|
|
||||||
address borrowToken;
|
return actions;
|
||||||
uint balanceBefore;
|
}
|
||||||
if (setId != 0) {
|
|
||||||
address borrowToken = useUnderlying ? getUnderlyingToken(borrowCurrencyId) : getAssetToken(borrowCurrencyId);
|
|
||||||
balanceBefore = TokenInterface(borrowToken).balanceOf(address(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
notional.batchBalanceAndTradeAction{value: msgValue}(address(this), action);
|
function depositCollateralBorrowAndWithdraw(
|
||||||
|
uint16 depositCurrencyId,
|
||||||
|
bool useUnderlying,
|
||||||
|
uint256 depositAmount,
|
||||||
|
uint16 borrowCurrencyId,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount,
|
||||||
|
uint32 maxBorrowRate,
|
||||||
|
bool redeemToUnderlying,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
require(depositCurrencyId != borrowCurrencyId);
|
||||||
|
|
||||||
if (setId != 0) {
|
depositAmount = getDepositAmountAndSetApproval(
|
||||||
setUint(setId, sub(TokenInterface(borrowToken).balanceOf(address(this)), balanceBefore));
|
getId,
|
||||||
}
|
depositCurrencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount
|
||||||
|
);
|
||||||
|
|
||||||
// todo: events
|
BalanceActionWithTrades[]
|
||||||
|
memory actions = getDepositCollateralBorrowAndWithdrawActions(
|
||||||
|
depositCurrencyId,
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount,
|
||||||
|
borrowCurrencyId,
|
||||||
|
marketIndex,
|
||||||
|
fCashAmount,
|
||||||
|
maxBorrowRate,
|
||||||
|
redeemToUnderlying
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 msgValue = 0;
|
||||||
|
if (depositCurrencyId == ETH_CURRENCY_ID && useUnderlying)
|
||||||
|
msgValue = depositAmount;
|
||||||
|
|
||||||
|
executeTradeActionWithBalanceChange(
|
||||||
|
actions,
|
||||||
|
msgValue,
|
||||||
|
borrowCurrencyId,
|
||||||
|
redeemToUnderlying,
|
||||||
|
setId
|
||||||
|
);
|
||||||
|
|
||||||
|
_eventName = "LogDepositCollateralBorrowAndWithdraw(address,bool,uint256,uint16,uint8,uint88,uint32,bool)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
useUnderlying,
|
||||||
|
depositAmount,
|
||||||
|
borrowCurrencyId,
|
||||||
|
marketIndex,
|
||||||
|
fCashAmount,
|
||||||
|
maxBorrowRate,
|
||||||
|
redeemToUnderlying
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdrawLend(
|
function withdrawLend(
|
||||||
|
@ -399,44 +545,96 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
uint8 marketIndex,
|
uint8 marketIndex,
|
||||||
uint88 fCashAmount,
|
uint88 fCashAmount,
|
||||||
uint32 maxBorrowRate,
|
uint32 maxBorrowRate,
|
||||||
uint getId,
|
uint256 setId
|
||||||
uint setId
|
)
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
bool useUnderlying = currencyId != ETH_CURRENCY_ID;
|
bool useUnderlying = currencyId != ETH_CURRENCY_ID;
|
||||||
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](1);
|
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](
|
||||||
|
1
|
||||||
|
);
|
||||||
action[0].actionType = DepositActionType.None;
|
action[0].actionType = DepositActionType.None;
|
||||||
action[0].currencyId = currencyId;
|
action[0].currencyId = currencyId;
|
||||||
// Withdraw borrowed amount to wallet
|
// Withdraw borrowed amount to wallet
|
||||||
action[0].withdrawEntireCashBalance = true;
|
action[0].withdrawEntireCashBalance = true;
|
||||||
// TODO: will redeem underlying work with ETH?
|
|
||||||
action[0].redeemToUnderlying = useUnderlying;
|
action[0].redeemToUnderlying = useUnderlying;
|
||||||
|
|
||||||
bytes32[] memory trades = new bytes32[](1);
|
bytes32[] memory trades = new bytes32[](1);
|
||||||
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
||||||
action[0].trades = trades;
|
action[0].trades = trades;
|
||||||
|
|
||||||
address tokenAddress;
|
executeTradeActionWithBalanceChange(
|
||||||
uint balanceBefore;
|
action,
|
||||||
if (setId != 0) {
|
0,
|
||||||
address tokenAddress = useUnderlying ? getUnderlyingToken(currencyId) : getAssetToken(currencyId);
|
currencyId,
|
||||||
balanceBefore = TokenInterface(tokenAddress).balanceOf(address(this));
|
useUnderlying,
|
||||||
}
|
setId
|
||||||
notional.batchBalanceAndTradeAction(address(this), action);
|
);
|
||||||
|
|
||||||
if (setId != 0) {
|
_eventName = "LogWithdrawLend(address,uint16,uint8,uint88,uint32)";
|
||||||
setUint(setId, sub(TokenInterface(tokenAddress).balanceOf(address(this)), balanceBefore));
|
_eventParam = abi.encode(
|
||||||
}
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
marketIndex,
|
||||||
|
fCashAmount,
|
||||||
|
maxBorrowRate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function repayBorrow(
|
function repayBorrow(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint8 marketIndex,
|
uint8 marketIndex,
|
||||||
uint fCashAmount,
|
int88 netCashToAccount,
|
||||||
uint minLendRate,
|
uint32 minLendRate,
|
||||||
uint getId,
|
uint256 setId
|
||||||
uint setId
|
)
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
external
|
||||||
// might want to use getfCashAmountGivenCashAmount
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
int256 fCashAmount = notional.getfCashAmountGivenCashAmount(
|
||||||
|
currencyId,
|
||||||
|
int88(int256(netCashToAccount).neg()),
|
||||||
|
marketIndex,
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
bool useUnderlying = currencyId != ETH_CURRENCY_ID;
|
||||||
|
BalanceActionWithTrades[] memory action = new BalanceActionWithTrades[](
|
||||||
|
1
|
||||||
|
);
|
||||||
|
action[0].actionType = DepositActionType.None;
|
||||||
|
action[0].currencyId = currencyId;
|
||||||
|
// Withdraw borrowed amount to wallet
|
||||||
|
action[0].withdrawEntireCashBalance = true;
|
||||||
|
action[0].redeemToUnderlying = useUnderlying;
|
||||||
|
|
||||||
|
bytes32[] memory trades = new bytes32[](1);
|
||||||
|
trades[0] = encodeLendTrade(
|
||||||
|
marketIndex,
|
||||||
|
uint88(fCashAmount),
|
||||||
|
minLendRate
|
||||||
|
);
|
||||||
|
action[0].trades = trades;
|
||||||
|
|
||||||
|
executeTradeActionWithBalanceChange(
|
||||||
|
action,
|
||||||
|
0,
|
||||||
|
currencyId,
|
||||||
|
useUnderlying,
|
||||||
|
setId
|
||||||
|
);
|
||||||
|
|
||||||
|
_eventName = "LogRepayBorrow(address,uint16,uint8,uint88,uint32)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
address(this),
|
||||||
|
currencyId,
|
||||||
|
marketIndex,
|
||||||
|
netCashToAccount,
|
||||||
|
minLendRate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,11 +643,18 @@ abstract contract NotionalResolver is Events, Helpers {
|
||||||
* getId or setId integration. This can be used to roll lends and borrows forward.
|
* getId or setId integration. This can be used to roll lends and borrows forward.
|
||||||
* @param actions a set of BatchActionWithTrades that will be executed for this account
|
* @param actions a set of BatchActionWithTrades that will be executed for this account
|
||||||
*/
|
*/
|
||||||
function batchActionRaw(
|
function batchActionRaw(BalanceActionWithTrades[] memory actions)
|
||||||
BalanceActionWithTrades[] memory actions
|
external
|
||||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
notional.batchBalanceAndTradeAction(address(this), actions);
|
notional.batchBalanceAndTradeAction(address(this), actions);
|
||||||
|
|
||||||
// todo: events
|
_eventName = "LogBatchActionRaw(address)";
|
||||||
|
_eventParam = abi.encode(address(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contract ConnectV2Notional is NotionalResolver {
|
||||||
|
string public name = "Notional-v1.1";
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user