Addressing PR comments

This commit is contained in:
Tianjie Wei 2022-03-31 08:27:31 -07:00
parent 7534ddd4ad
commit 74a7effdb4
6 changed files with 953 additions and 953 deletions

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6; pragma solidity ^0.7.6;
contract Events { contract Events {

View File

@ -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;
}
} }

View File

@ -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

View File

@ -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]
} }
]; ];

View File

@ -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 () {