mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Addressing PR comments
This commit is contained in:
parent
7534ddd4ad
commit
74a7effdb4
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
contract Events {
|
contract Events {
|
||||||
|
|
|
@ -1,286 +1,276 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
pragma abicoder v2;
|
pragma abicoder v2;
|
||||||
|
|
||||||
import {Token, NotionalInterface, BalanceAction, BalanceActionWithTrades, DepositActionType} from "./interface.sol";
|
import { Token, NotionalInterface, BalanceAction, BalanceActionWithTrades, DepositActionType } from "./interface.sol";
|
||||||
import {Basic} from "../../common/basic.sol";
|
import { Basic } from "../../common/basic.sol";
|
||||||
import {DSMath} from "../../common/math.sol";
|
import { DSMath } from "../../common/math.sol";
|
||||||
import {TokenInterface} from "../../common/interfaces.sol";
|
import { TokenInterface } from "../../common/interfaces.sol";
|
||||||
|
|
||||||
abstract contract Helpers is DSMath, Basic {
|
abstract contract Helpers is DSMath, Basic {
|
||||||
uint8 internal constant LEND_TRADE = 0;
|
uint8 internal constant LEND_TRADE = 0;
|
||||||
uint8 internal constant BORROW_TRADE = 1;
|
uint8 internal constant BORROW_TRADE = 1;
|
||||||
uint256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
uint256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
||||||
uint256 internal constant ETH_CURRENCY_ID = 1;
|
uint256 internal constant ETH_CURRENCY_ID = 1;
|
||||||
uint256 internal constant MAX_DEPOSIT = uint256(-1);
|
uint256 internal constant MAX_DEPOSIT = type(uint256).max;
|
||||||
|
|
||||||
/// @dev Contract address is different on Kovan: 0x0EAE7BAdEF8f95De91fDDb74a89A786cF891Eb0e
|
/// @dev Contract address is different on Kovan: 0x0EAE7BAdEF8f95De91fDDb74a89A786cF891Eb0e
|
||||||
NotionalInterface internal constant notional =
|
NotionalInterface internal constant notional =
|
||||||
NotionalInterface(0x1344A36A1B56144C3Bc62E7757377D288fDE0369);
|
NotionalInterface(0x1344A36A1B56144C3Bc62E7757377D288fDE0369);
|
||||||
|
|
||||||
/// @notice Returns the address of the underlying token for a given currency id,
|
/// @notice Returns the address of the underlying token for a given currency id,
|
||||||
function getUnderlyingToken(uint16 currencyId)
|
function getAssetOrUnderlyingToken(uint16 currencyId, bool underlying)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (address)
|
returns (address)
|
||||||
{
|
{
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
(/* assetToken */, Token memory underlyingToken) = notional.getCurrency(currencyId);
|
(Token memory assetToken, Token memory underlyingToken) = notional.getCurrency(currencyId);
|
||||||
return underlyingToken.tokenAddress;
|
return
|
||||||
}
|
underlying ? underlyingToken.tokenAddress : assetToken.tokenAddress;
|
||||||
|
}
|
||||||
|
|
||||||
/// @notice Returns the address of the asset token for a given currency id
|
function getCashOrNTokenBalance(uint16 currencyId, bool nToken)
|
||||||
function getAssetToken(uint16 currencyId) internal view returns (address) {
|
internal
|
||||||
// prettier-ignore
|
view
|
||||||
(Token memory assetToken, /* underlyingToken */) = notional.getCurrency(currencyId);
|
returns (uint256)
|
||||||
return assetToken.tokenAddress;
|
{
|
||||||
}
|
// prettier-ignore
|
||||||
|
(
|
||||||
function getCashBalance(uint16 currencyId)
|
int256 cashBalance,
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (int256 cashBalance)
|
|
||||||
{
|
|
||||||
// prettier-ignore
|
|
||||||
(
|
|
||||||
cashBalance,
|
|
||||||
/* int256 nTokenBalance */,
|
|
||||||
/* int256 lastClaimTime */
|
|
||||||
) = notional.getAccountBalance(currencyId, address(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNTokenBalance(uint16 currencyId)
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
// prettier-ignore
|
|
||||||
(
|
|
||||||
/* int256 cashBalance */,
|
|
||||||
int256 nTokenBalance,
|
int256 nTokenBalance,
|
||||||
/* int256 lastClaimTime */
|
/* int256 lastClaimTime */
|
||||||
) = notional.getAccountBalance(currencyId, address(this));
|
) = notional.getAccountBalance(currencyId, address(this));
|
||||||
return toUint(nTokenBalance);
|
return toUint(nToken ? nTokenBalance : cashBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNTokenRedeemAmount(
|
function getNTokenRedeemAmount(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint96 _tokensToRedeem,
|
uint96 _tokensToRedeem,
|
||||||
uint256 getId
|
uint256 getId
|
||||||
) internal returns (uint96 tokensToRedeem) {
|
) internal returns (uint96 tokensToRedeem) {
|
||||||
tokensToRedeem = uint96(getUint(getId, _tokensToRedeem));
|
tokensToRedeem = toUint96(getUint(getId, _tokensToRedeem));
|
||||||
if (tokensToRedeem == uint96(-1)) {
|
if (tokensToRedeem == type(uint96).max) {
|
||||||
tokensToRedeem = uint96(getNTokenBalance(currencyId));
|
tokensToRedeem = toUint96(getCashOrNTokenBalance(currencyId, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMsgValue(
|
function toUint96(uint256 value) internal pure returns (uint96) {
|
||||||
uint16 currencyId,
|
require(value <= type(uint96).max, "uint96 value overflow");
|
||||||
bool useUnderlying,
|
return uint96(value);
|
||||||
uint256 depositAmount
|
}
|
||||||
) internal pure returns (uint256 msgValue) {
|
|
||||||
msgValue = (currencyId == ETH_CURRENCY_ID && useUnderlying)
|
|
||||||
? depositAmount
|
|
||||||
: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertToInternal(uint16 currencyId, uint256 amount)
|
function toUint88(uint256 value) internal pure returns (uint88) {
|
||||||
internal
|
require(value <= type(uint88).max, "uint88 value overflow");
|
||||||
view
|
return uint88(value);
|
||||||
returns (uint256)
|
}
|
||||||
{
|
|
||||||
// If token decimals is greater than INTERNAL_TOKEN_PRECISION then this will truncate
|
|
||||||
// down to the internal precision. Resulting dust will accumulate to the protocol.
|
|
||||||
// If token decimals is less than INTERNAL_TOKEN_PRECISION then this will add zeros to the
|
|
||||||
// end of amount and will not result in dust.
|
|
||||||
// prettier-ignore
|
|
||||||
(Token memory assetToken, /* underlyingToken */) = notional.getCurrency(currencyId);
|
|
||||||
uint256 decimals = toUint(assetToken.decimals);
|
|
||||||
if (decimals == INTERNAL_TOKEN_PRECISION) return amount;
|
|
||||||
return div(mul(amount, INTERNAL_TOKEN_PRECISION), decimals);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeLendTrade(
|
function getMsgValue(
|
||||||
uint8 marketIndex,
|
uint16 currencyId,
|
||||||
uint88 fCashAmount,
|
bool useUnderlying,
|
||||||
uint32 minLendRate
|
uint256 depositAmount
|
||||||
) internal pure returns (bytes32) {
|
) internal pure returns (uint256 msgValue) {
|
||||||
return
|
msgValue = (currencyId == ETH_CURRENCY_ID && useUnderlying)
|
||||||
(bytes32(uint256(LEND_TRADE)) << 248) |
|
? depositAmount
|
||||||
(bytes32(uint256(marketIndex)) << 240) |
|
: 0;
|
||||||
(bytes32(uint256(fCashAmount)) << 152) |
|
}
|
||||||
(bytes32(uint256(minLendRate)) << 120);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeBorrowTrade(
|
function convertToInternal(uint16 currencyId, uint256 amount)
|
||||||
uint8 marketIndex,
|
internal
|
||||||
uint88 fCashAmount,
|
view
|
||||||
uint32 maxBorrowRate
|
returns (uint256)
|
||||||
) internal pure returns (bytes32) {
|
{
|
||||||
return
|
// If token decimals is greater than INTERNAL_TOKEN_PRECISION then this will truncate
|
||||||
(bytes32(uint256(BORROW_TRADE)) << 248) |
|
// down to the internal precision. Resulting dust will accumulate to the protocol.
|
||||||
(bytes32(uint256(marketIndex)) << 240) |
|
// If token decimals is less than INTERNAL_TOKEN_PRECISION then this will add zeros to the
|
||||||
(bytes32(uint256(fCashAmount)) << 152) |
|
// end of amount and will not result in dust.
|
||||||
(bytes32(uint256(maxBorrowRate)) << 120);
|
// prettier-ignore
|
||||||
}
|
(Token memory assetToken, /* underlyingToken */) = notional.getCurrency(currencyId);
|
||||||
|
uint256 decimals = toUint(assetToken.decimals);
|
||||||
|
if (decimals == INTERNAL_TOKEN_PRECISION) return amount;
|
||||||
|
return div(mul(amount, INTERNAL_TOKEN_PRECISION), decimals);
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Uses getId to set approval for the given token up to the specified deposit
|
function encodeLendTrade(
|
||||||
/// amount only
|
uint8 marketIndex,
|
||||||
function getDepositAmountAndSetApproval(
|
uint88 fCashAmount,
|
||||||
uint256 getId,
|
uint32 minLendRate
|
||||||
uint16 currencyId,
|
) internal pure returns (bytes32) {
|
||||||
bool useUnderlying,
|
return
|
||||||
uint256 depositAmount
|
(bytes32(uint256(LEND_TRADE)) << 248) |
|
||||||
) internal returns (uint256) {
|
(bytes32(uint256(marketIndex)) << 240) |
|
||||||
depositAmount = getUint(getId, depositAmount);
|
(bytes32(uint256(fCashAmount)) << 152) |
|
||||||
if (currencyId == ETH_CURRENCY_ID && useUnderlying) {
|
(bytes32(uint256(minLendRate)) << 120);
|
||||||
// No approval required for ETH so we can return the deposit amount
|
}
|
||||||
return
|
|
||||||
depositAmount == MAX_DEPOSIT
|
|
||||||
? address(this).balance
|
|
||||||
: depositAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
address tokenAddress = useUnderlying
|
function encodeBorrowTrade(
|
||||||
? getUnderlyingToken(currencyId)
|
uint8 marketIndex,
|
||||||
: getAssetToken(currencyId);
|
uint88 fCashAmount,
|
||||||
|
uint32 maxBorrowRate
|
||||||
|
) internal pure returns (bytes32) {
|
||||||
|
return
|
||||||
|
(bytes32(uint256(BORROW_TRADE)) << 248) |
|
||||||
|
(bytes32(uint256(marketIndex)) << 240) |
|
||||||
|
(bytes32(uint256(fCashAmount)) << 152) |
|
||||||
|
(bytes32(uint256(maxBorrowRate)) << 120);
|
||||||
|
}
|
||||||
|
|
||||||
if (depositAmount == MAX_DEPOSIT) {
|
/// @dev Uses getId to set approval for the given token up to the specified deposit
|
||||||
depositAmount = TokenInterface(tokenAddress).balanceOf(
|
/// amount only
|
||||||
address(this)
|
function getDepositAmountAndSetApproval(
|
||||||
);
|
uint256 getId,
|
||||||
}
|
uint16 currencyId,
|
||||||
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
bool useUnderlying,
|
||||||
return depositAmount;
|
uint256 depositAmount
|
||||||
}
|
) internal returns (uint256) {
|
||||||
|
depositAmount = getUint(getId, depositAmount);
|
||||||
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying) {
|
||||||
|
// No approval required for ETH so we can return the deposit amount
|
||||||
|
return
|
||||||
|
depositAmount == MAX_DEPOSIT
|
||||||
|
? address(this).balance
|
||||||
|
: depositAmount;
|
||||||
|
}
|
||||||
|
|
||||||
function getBalance(address addr) internal view returns (uint256) {
|
address tokenAddress = getAssetOrUnderlyingToken(
|
||||||
if (addr == ethAddr) {
|
currencyId,
|
||||||
return address(this).balance;
|
useUnderlying
|
||||||
}
|
);
|
||||||
|
|
||||||
return TokenInterface(addr).balanceOf(address(this));
|
if (depositAmount == MAX_DEPOSIT) {
|
||||||
}
|
depositAmount = TokenInterface(tokenAddress).balanceOf(
|
||||||
|
address(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
approve(TokenInterface(tokenAddress), address(notional), depositAmount);
|
||||||
|
return depositAmount;
|
||||||
|
}
|
||||||
|
|
||||||
function getAddress(uint16 currencyId, bool useUnderlying)
|
function getBalance(address addr) internal view returns (uint256) {
|
||||||
internal
|
if (addr == ethAddr) {
|
||||||
view
|
return address(this).balance;
|
||||||
returns (address)
|
}
|
||||||
{
|
|
||||||
if (currencyId == ETH_CURRENCY_ID && useUnderlying) {
|
|
||||||
return ethAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return TokenInterface(addr).balanceOf(address(this));
|
||||||
useUnderlying
|
}
|
||||||
? getUnderlyingToken(currencyId)
|
|
||||||
: getAssetToken(currencyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Executes a trade action and sets the balance change to setId
|
function getAddress(uint16 currencyId, bool useUnderlying)
|
||||||
function executeTradeActionWithBalanceChange(
|
internal
|
||||||
BalanceActionWithTrades[] memory action,
|
view
|
||||||
uint256 msgValue,
|
returns (address)
|
||||||
uint16 currencyId,
|
{
|
||||||
bool useUnderlying,
|
if (currencyId == ETH_CURRENCY_ID && useUnderlying) {
|
||||||
uint256 setId
|
return ethAddr;
|
||||||
) internal {
|
}
|
||||||
address tokenAddress;
|
|
||||||
uint256 balanceBefore;
|
|
||||||
if (setId != 0) {
|
|
||||||
tokenAddress = getAddress(currencyId, useUnderlying);
|
|
||||||
balanceBefore = getBalance(tokenAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
notional.batchBalanceAndTradeAction{value: msgValue}(
|
return getAssetOrUnderlyingToken(currencyId, useUnderlying);
|
||||||
address(this),
|
}
|
||||||
action
|
|
||||||
);
|
|
||||||
|
|
||||||
if (setId != 0) {
|
/// @dev Executes a trade action and sets the balance change to setId
|
||||||
uint256 balanceAfter = getBalance(tokenAddress);
|
function executeTradeActionWithBalanceChange(
|
||||||
setUint(setId, sub(balanceAfter, balanceBefore));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Executes a balance action and sets the balance change to setId
|
notional.batchBalanceAndTradeAction{ value: msgValue }(
|
||||||
function executeActionWithBalanceChange(
|
address(this),
|
||||||
BalanceAction[] memory action,
|
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, sub(balanceAfter, balanceBefore));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (setId != 0) {
|
/// @dev Executes a balance action and sets the balance change to setId
|
||||||
uint256 balanceAfter = getBalance(tokenAddress);
|
function executeActionWithBalanceChange(
|
||||||
setUint(setId, sub(balanceAfter, balanceBefore));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
function getDepositCollateralBorrowAndWithdrawActions(
|
notional.batchBalanceAction{ value: msgValue }(address(this), action);
|
||||||
uint16 depositCurrencyId,
|
|
||||||
DepositActionType depositAction,
|
|
||||||
uint256 depositAmount,
|
|
||||||
uint16 borrowCurrencyId,
|
|
||||||
uint8 marketIndex,
|
|
||||||
uint88 fCashAmount,
|
|
||||||
uint32 maxBorrowRate,
|
|
||||||
bool redeemToUnderlying
|
|
||||||
) internal returns (BalanceActionWithTrades[] memory action) {
|
|
||||||
BalanceActionWithTrades[] memory actions;
|
|
||||||
bytes32[] memory trades = new bytes32[](1);
|
|
||||||
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
|
||||||
|
|
||||||
if (depositCurrencyId == borrowCurrencyId) {
|
if (setId != 0) {
|
||||||
// In this case the account is likely borrowing against newly minted nTokens
|
uint256 balanceAfter = getBalance(tokenAddress);
|
||||||
// in the same currency. Technically the other deposit actions may work but
|
setUint(setId, sub(balanceAfter, balanceBefore));
|
||||||
// there's no good reason to borrow against cToken collateral
|
}
|
||||||
actions = new BalanceActionWithTrades[](1);
|
}
|
||||||
actions[0].actionType = depositAction;
|
|
||||||
actions[0].currencyId = depositCurrencyId;
|
|
||||||
actions[0].depositActionAmount = depositAmount;
|
|
||||||
// Withdraw borrowed amount to wallet
|
|
||||||
actions[0].withdrawEntireCashBalance = true;
|
|
||||||
actions[0].redeemToUnderlying = redeemToUnderlying;
|
|
||||||
actions[0].trades = trades;
|
|
||||||
|
|
||||||
return actions;
|
function getDepositCollateralBorrowAndWithdrawActions(
|
||||||
}
|
uint16 depositCurrencyId,
|
||||||
|
DepositActionType depositAction,
|
||||||
|
uint256 depositAmount,
|
||||||
|
uint16 borrowCurrencyId,
|
||||||
|
uint8 marketIndex,
|
||||||
|
uint88 fCashAmount,
|
||||||
|
uint32 maxBorrowRate,
|
||||||
|
bool redeemToUnderlying
|
||||||
|
) internal returns (BalanceActionWithTrades[] memory action) {
|
||||||
|
BalanceActionWithTrades[] memory actions;
|
||||||
|
bytes32[] memory trades = new bytes32[](1);
|
||||||
|
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
||||||
|
|
||||||
// This is the more common case that the account is borrowing against
|
if (depositCurrencyId == borrowCurrencyId) {
|
||||||
// collateral in a different currency
|
// In this case the account is likely borrowing against newly minted nTokens
|
||||||
actions = new BalanceActionWithTrades[](2);
|
// in the same currency. Technically the other deposit actions may work but
|
||||||
|
// there's no good reason to borrow against cToken collateral
|
||||||
|
actions = new BalanceActionWithTrades[](1);
|
||||||
|
actions[0].actionType = depositAction;
|
||||||
|
actions[0].currencyId = depositCurrencyId;
|
||||||
|
actions[0].depositActionAmount = depositAmount;
|
||||||
|
// Withdraw borrowed amount to wallet
|
||||||
|
actions[0].withdrawEntireCashBalance = true;
|
||||||
|
actions[0].redeemToUnderlying = redeemToUnderlying;
|
||||||
|
actions[0].trades = trades;
|
||||||
|
|
||||||
uint256 depositIndex;
|
return actions;
|
||||||
uint256 borrowIndex;
|
}
|
||||||
// Notional requires the batch actions to be ordered by currency id
|
|
||||||
if (depositCurrencyId < borrowCurrencyId) {
|
|
||||||
depositIndex = 0;
|
|
||||||
borrowIndex = 1;
|
|
||||||
} else {
|
|
||||||
depositIndex = 1;
|
|
||||||
borrowIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
actions[depositIndex].actionType = depositAction;
|
// This is the more common case that the account is borrowing against
|
||||||
actions[depositIndex].currencyId = depositCurrencyId;
|
// collateral in a different currency
|
||||||
actions[depositIndex].depositActionAmount = depositAmount;
|
actions = new BalanceActionWithTrades[](2);
|
||||||
|
|
||||||
actions[borrowIndex].actionType = DepositActionType.None;
|
uint256 depositIndex;
|
||||||
actions[borrowIndex].currencyId = borrowCurrencyId;
|
uint256 borrowIndex;
|
||||||
// Withdraw borrowed amount to wallet
|
// Notional requires the batch actions to be ordered by currency id
|
||||||
actions[borrowIndex].withdrawEntireCashBalance = true;
|
if (depositCurrencyId < borrowCurrencyId) {
|
||||||
actions[borrowIndex].redeemToUnderlying = redeemToUnderlying;
|
depositIndex = 0;
|
||||||
actions[borrowIndex].trades = trades;
|
borrowIndex = 1;
|
||||||
|
} else {
|
||||||
|
depositIndex = 1;
|
||||||
|
borrowIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return actions;
|
actions[depositIndex].actionType = depositAction;
|
||||||
}
|
actions[depositIndex].currencyId = depositCurrencyId;
|
||||||
|
actions[depositIndex].depositActionAmount = depositAmount;
|
||||||
|
|
||||||
|
actions[borrowIndex].actionType = DepositActionType.None;
|
||||||
|
actions[borrowIndex].currencyId = borrowCurrencyId;
|
||||||
|
// Withdraw borrowed amount to wallet
|
||||||
|
actions[borrowIndex].withdrawEntireCashBalance = true;
|
||||||
|
actions[borrowIndex].redeemToUnderlying = redeemToUnderlying;
|
||||||
|
actions[borrowIndex].trades = trades;
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.6;
|
pragma solidity ^0.7.6;
|
||||||
pragma abicoder v2;
|
pragma abicoder v2;
|
||||||
|
|
||||||
|
@ -8,126 +9,127 @@ pragma abicoder v2;
|
||||||
/// - Ether: the one and only
|
/// - Ether: the one and only
|
||||||
/// - NonMintable: tokens that do not have an underlying (therefore not cTokens)
|
/// - NonMintable: tokens that do not have an underlying (therefore not cTokens)
|
||||||
enum TokenType {
|
enum TokenType {
|
||||||
UnderlyingToken,
|
UnderlyingToken,
|
||||||
cToken,
|
cToken,
|
||||||
cETH,
|
cETH,
|
||||||
Ether,
|
Ether,
|
||||||
NonMintable
|
NonMintable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Specifies different deposit actions that can occur during BalanceAction or BalanceActionWithTrades
|
/// @notice Specifies different deposit actions that can occur during BalanceAction or BalanceActionWithTrades
|
||||||
enum DepositActionType {
|
enum DepositActionType {
|
||||||
// No deposit action
|
// No deposit action
|
||||||
None,
|
None,
|
||||||
// Deposit asset cash, depositActionAmount is specified in asset cash external precision
|
// Deposit asset cash, depositActionAmount is specified in asset cash external precision
|
||||||
DepositAsset,
|
DepositAsset,
|
||||||
// Deposit underlying tokens that are mintable to asset cash, depositActionAmount is specified in underlying token
|
// Deposit underlying tokens that are mintable to asset cash, depositActionAmount is specified in underlying token
|
||||||
// external precision
|
// external precision
|
||||||
DepositUnderlying,
|
DepositUnderlying,
|
||||||
// Deposits specified asset cash external precision amount into an nToken and mints the corresponding amount of
|
// Deposits specified asset cash external precision amount into an nToken and mints the corresponding amount of
|
||||||
// nTokens into the account
|
// nTokens into the account
|
||||||
DepositAssetAndMintNToken,
|
DepositAssetAndMintNToken,
|
||||||
// Deposits specified underlying in external precision, mints asset cash, and uses that asset cash to mint nTokens
|
// Deposits specified underlying in external precision, mints asset cash, and uses that asset cash to mint nTokens
|
||||||
DepositUnderlyingAndMintNToken,
|
DepositUnderlyingAndMintNToken,
|
||||||
// Redeems an nToken balance to asset cash. depositActionAmount is specified in nToken precision. Considered a deposit action
|
// Redeems an nToken balance to asset cash. depositActionAmount is specified in nToken precision. Considered a deposit action
|
||||||
// because it deposits asset cash into an account. If there are fCash residuals that cannot be sold off, will revert.
|
// because it deposits asset cash into an account. If there are fCash residuals that cannot be sold off, will revert.
|
||||||
RedeemNToken,
|
RedeemNToken,
|
||||||
// Converts specified amount of asset cash balance already in Notional to nTokens. depositActionAmount is specified in
|
// Converts specified amount of asset cash balance already in Notional to nTokens. depositActionAmount is specified in
|
||||||
// Notional internal 8 decimal precision.
|
// Notional internal 8 decimal precision.
|
||||||
ConvertCashToNToken
|
ConvertCashToNToken
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Defines a balance action with a set of trades to do as well
|
/// @notice Defines a balance action with a set of trades to do as well
|
||||||
struct BalanceActionWithTrades {
|
struct BalanceActionWithTrades {
|
||||||
DepositActionType actionType;
|
DepositActionType actionType;
|
||||||
uint16 currencyId;
|
uint16 currencyId;
|
||||||
uint256 depositActionAmount;
|
uint256 depositActionAmount;
|
||||||
uint256 withdrawAmountInternalPrecision;
|
uint256 withdrawAmountInternalPrecision;
|
||||||
bool withdrawEntireCashBalance;
|
bool withdrawEntireCashBalance;
|
||||||
bool redeemToUnderlying;
|
bool redeemToUnderlying;
|
||||||
// Array of tightly packed 32 byte objects that represent trades. See TradeActionType documentation
|
// Array of tightly packed 32 byte objects that represent trades. See TradeActionType documentation
|
||||||
bytes32[] trades;
|
bytes32[] trades;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Defines a balance action for batchAction
|
/// @notice Defines a balance action for batchAction
|
||||||
struct BalanceAction {
|
struct BalanceAction {
|
||||||
// Deposit action to take (if any)
|
// Deposit action to take (if any)
|
||||||
DepositActionType actionType;
|
DepositActionType actionType;
|
||||||
uint16 currencyId;
|
uint16 currencyId;
|
||||||
// Deposit action amount must correspond to the depositActionType, see documentation above.
|
// Deposit action amount must correspond to the depositActionType, see documentation above.
|
||||||
uint256 depositActionAmount;
|
uint256 depositActionAmount;
|
||||||
// Withdraw an amount of asset cash specified in Notional internal 8 decimal precision
|
// Withdraw an amount of asset cash specified in Notional internal 8 decimal precision
|
||||||
uint256 withdrawAmountInternalPrecision;
|
uint256 withdrawAmountInternalPrecision;
|
||||||
// If set to true, will withdraw entire cash balance. Useful if there may be an unknown amount of asset cash
|
// If set to true, will withdraw entire cash balance. Useful if there may be an unknown amount of asset cash
|
||||||
// residual left from trading.
|
// residual left from trading.
|
||||||
bool withdrawEntireCashBalance;
|
bool withdrawEntireCashBalance;
|
||||||
// If set to true, will redeem asset cash to the underlying token on withdraw.
|
// If set to true, will redeem asset cash to the underlying token on withdraw.
|
||||||
bool redeemToUnderlying;
|
bool redeemToUnderlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token {
|
struct Token {
|
||||||
// Address of the token
|
// Address of the token
|
||||||
address tokenAddress;
|
address tokenAddress;
|
||||||
// True if the token has a transfer fee which is used internally to determine
|
// True if the token has a transfer fee which is used internally to determine
|
||||||
// the proper balance change
|
// the proper balance change
|
||||||
bool hasTransferFee;
|
bool hasTransferFee;
|
||||||
// Decimal precision of the token as a power of 10
|
// Decimal precision of the token as a power of 10
|
||||||
int256 decimals;
|
int256 decimals;
|
||||||
// Type of token, enumerated above
|
// Type of token, enumerated above
|
||||||
TokenType tokenType;
|
TokenType tokenType;
|
||||||
// Used internally for tokens that have a collateral cap, zero if there is no cap
|
// Used internally for tokens that have a collateral cap, zero if there is no cap
|
||||||
uint256 maxCollateralBalance;
|
uint256 maxCollateralBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NotionalInterface {
|
interface NotionalInterface {
|
||||||
function getCurrency(uint16 currencyId)
|
function getCurrency(uint16 currencyId)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (Token memory assetToken, Token memory underlyingToken);
|
returns (Token memory assetToken, Token memory underlyingToken);
|
||||||
|
|
||||||
function getAccountBalance(uint16 currencyId, address account)
|
function getAccountBalance(uint16 currencyId, address account)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (
|
returns (
|
||||||
int256 cashBalance,
|
int256 cashBalance,
|
||||||
int256 nTokenBalance,
|
int256 nTokenBalance,
|
||||||
uint256 lastClaimTime
|
uint256 lastClaimTime
|
||||||
);
|
);
|
||||||
|
|
||||||
function depositUnderlyingToken(
|
function depositUnderlyingToken(
|
||||||
address account,
|
address account,
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint256 amountExternalPrecision
|
uint256 amountExternalPrecision
|
||||||
) external payable returns (uint256);
|
) external payable returns (uint256);
|
||||||
|
|
||||||
function depositAssetToken(
|
function depositAssetToken(
|
||||||
address account,
|
address account,
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint256 amountExternalPrecision
|
uint256 amountExternalPrecision
|
||||||
) external returns (uint256);
|
) external returns (uint256);
|
||||||
|
|
||||||
function withdraw(
|
function withdraw(
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint88 amountInternalPrecision,
|
uint88 amountInternalPrecision,
|
||||||
bool redeemToUnderlying
|
bool redeemToUnderlying
|
||||||
) external returns (uint256);
|
) external returns (uint256);
|
||||||
|
|
||||||
function nTokenClaimIncentives() external returns (uint256);
|
function nTokenClaimIncentives() external returns (uint256);
|
||||||
|
|
||||||
function nTokenRedeem(
|
function nTokenRedeem(
|
||||||
address redeemer,
|
address redeemer,
|
||||||
uint16 currencyId,
|
uint16 currencyId,
|
||||||
uint96 tokensToRedeem_,
|
uint96 tokensToRedeem_,
|
||||||
bool sellTokenAssets
|
bool sellTokenAssets,
|
||||||
) external returns (int256);
|
bool acceptResidualAssets
|
||||||
|
) external returns (int256);
|
||||||
|
|
||||||
function batchBalanceAction(
|
function batchBalanceAction(
|
||||||
address account,
|
address account,
|
||||||
BalanceAction[] calldata actions
|
BalanceAction[] calldata actions
|
||||||
) external payable;
|
) external payable;
|
||||||
|
|
||||||
function batchBalanceAndTradeAction(
|
function batchBalanceAndTradeAction(
|
||||||
address account,
|
address account,
|
||||||
BalanceActionWithTrades[] calldata actions
|
BalanceActionWithTrades[] calldata actions
|
||||||
) external payable;
|
) external payable;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -95,7 +95,7 @@ const redeemNTokenRaw = async (
|
||||||
{
|
{
|
||||||
connector: "NOTIONAL-TEST-A",
|
connector: "NOTIONAL-TEST-A",
|
||||||
method: "redeemNTokenRaw",
|
method: "redeemNTokenRaw",
|
||||||
args: [currencyId, sellTokenAssets, tokensToRedeem, 0, 0]
|
args: [currencyId, sellTokenAssets, tokensToRedeem, false, 0, 0]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ describe("Notional", function () {
|
||||||
forking: {
|
forking: {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
||||||
blockNumber: 13798624,
|
blockNumber: 14483893,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -240,7 +240,7 @@ describe("Notional", function () {
|
||||||
expect(
|
expect(
|
||||||
await daiToken.balanceOf(dsaWallet0.address),
|
await daiToken.balanceOf(dsaWallet0.address),
|
||||||
"expect DSA wallet to contain borrowed balance minus fees"
|
"expect DSA wallet to contain borrowed balance minus fees"
|
||||||
).to.be.gte(ethers.utils.parseEther("990"));
|
).to.be.gte(ethers.utils.parseEther("985"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("test_deposit_ETH_and_borrow_DAI_asset", async function () {
|
it("test_deposit_ETH_and_borrow_DAI_asset", async function () {
|
||||||
|
@ -256,7 +256,7 @@ describe("Notional", function () {
|
||||||
expect(
|
expect(
|
||||||
await cdaiToken.balanceOf(dsaWallet0.address),
|
await cdaiToken.balanceOf(dsaWallet0.address),
|
||||||
"expect DSA wallet to contain borrowed balance minus fees"
|
"expect DSA wallet to contain borrowed balance minus fees"
|
||||||
).to.be.gte(ethers.utils.parseUnits("4500000000000", 0));
|
).to.be.gte(ethers.utils.parseUnits("4490000000000", 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("test_deposit_DAI_underlying_and_borrow_ETH", async function () {
|
it("test_deposit_DAI_underlying_and_borrow_ETH", async function () {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user