Add is destination vault will be safe condition

This commit is contained in:
Shivva 2020-11-23 08:17:25 +01:00 committed by Luis Schliesske
parent b3887c6e37
commit 7803bc5102
23 changed files with 578 additions and 26 deletions

View File

@ -16,3 +16,6 @@ address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
// Insta Pool // Insta Pool
address constant INSTA_POOL_RESOLVER = 0xa004a5afBa04b74037E9E52bA1f7eb02b5E61509; address constant INSTA_POOL_RESOLVER = 0xa004a5afBa04b74037E9E52bA1f7eb02b5E61509;
uint256 constant ROUTE_1_TOLERANCE = 1005e15; uint256 constant ROUTE_1_TOLERANCE = 1005e15;
// Insta Mapping
address constant INSTA_MAPPING = 0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88;

View File

@ -0,0 +1,77 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
import {
GelatoConditionsStandard
} from "@gelatonetwork/core/contracts/conditions/GelatoConditionsStandard.sol";
import {
_getMakerVaultDebt,
_getMakerVaultCollateralBalance,
_isVaultWillBeSafe,
_isNewVaultWillBeSafe
} from "../../../functions/dapps/FMaker.sol";
import {
_getRealisedDebt
} from "../../../functions/gelato/FGelatoDebtBridge.sol";
import {GelatoBytes} from "../../../lib/GelatoBytes.sol";
import "hardhat/console.sol";
contract ConditionIsDestVaultWillBeSafe is GelatoConditionsStandard {
using GelatoBytes for bytes;
function getConditionData(
uint256 _fromVaultId,
uint256 _destVaultId,
string memory _destColType
) public pure virtual returns (bytes memory) {
return abi.encode(_fromVaultId, _destVaultId, _destColType);
}
function ok(
uint256,
bytes calldata _conditionData,
uint256
) public view virtual override returns (string memory) {
(
uint256 _fromVaultId,
uint256 _destVaultId,
string memory _destColType
) = abi.decode(_conditionData, (uint256, uint256, string));
return destVaultWillBeSafe(_fromVaultId, _destVaultId, _destColType);
}
function destVaultWillBeSafe(
uint256 _fromVaultId,
uint256 _destVaultId,
string memory _destColType
) public view returns (string memory) {
uint256 wDaiToBorrow =
_getRealisedDebt(_getMakerVaultDebt(_fromVaultId));
uint256 wColToDeposit = _getMakerVaultCollateralBalance(_fromVaultId);
return
isDestVaultWillBeSafe(
_destVaultId,
wDaiToBorrow,
wColToDeposit,
_destColType
)
? OK
: "DestVaultWillNotBeSafe";
}
function isDestVaultWillBeSafe(
uint256 _vaultId,
uint256 _wDaiToBorrow,
uint256 _wColToDeposit,
string memory _colType
) public view returns (bool) {
return
_vaultId == 0
? _isNewVaultWillBeSafe(_colType, _wDaiToBorrow, _wColToDeposit)
: _isVaultWillBeSafe(_vaultId, _wDaiToBorrow, _wColToDeposit);
}
}

View File

@ -4,7 +4,9 @@ pragma solidity 0.7.4;
import { import {
_getMakerRawVaultDebt, _getMakerRawVaultDebt,
_getMakerVaultDebt, _getMakerVaultDebt,
_getMakerVaultCollateralBalance _getMakerVaultCollateralBalance,
_isVaultWillBeSafe,
_isNewVaultWillBeSafe
} from "../../functions/dapps/FMaker.sol"; } from "../../functions/dapps/FMaker.sol";
contract MakerResolver { contract MakerResolver {
@ -29,4 +31,20 @@ contract MakerResolver {
{ {
return _getMakerVaultCollateralBalance(_vaultId); return _getMakerVaultCollateralBalance(_vaultId);
} }
function isVaultWillBeSafe(
uint256 _vaultId,
uint256 _amtToBorrow,
uint256 _colToDeposit
) public view returns (bool) {
return _isVaultWillBeSafe(_vaultId, _amtToBorrow, _colToDeposit);
}
function isNewVaultWillBeSafe(
string memory _colType,
uint256 _amtToBorrow,
uint256 _colToDeposit
) public view returns (bool) {
return _isNewVaultWillBeSafe(_colType, _amtToBorrow, _colToDeposit);
}
} }

View File

@ -2,9 +2,15 @@
pragma solidity 0.7.4; pragma solidity 0.7.4;
import {MCD_MANAGER} from "../../constants/CMaker.sol"; import {MCD_MANAGER} from "../../constants/CMaker.sol";
import {INSTA_MAPPING} from "../../constants/CInstaDapp.sol";
import {
ITokenJoinInterface
} from "../../interfaces/dapps/Maker/ITokenJoinInterface.sol";
import {IMcdManager} from "../../interfaces/dapps/Maker/IMcdManager.sol"; import {IMcdManager} from "../../interfaces/dapps/Maker/IMcdManager.sol";
import {InstaMapping} from "../../interfaces/InstaDapp/IInstaDapp.sol";
import {IVat} from "../../interfaces/dapps/Maker/IVat.sol"; import {IVat} from "../../interfaces/dapps/Maker/IVat.sol";
import {RAY, sub, mul} from "../../vendor/DSMath.sol"; import {RAY, add, sub, mul} from "../../vendor/DSMath.sol";
import {_stringToBytes32, _convertTo18} from "../../vendor/Convert.sol";
function _getMakerVaultDebt(uint256 _vaultId) view returns (uint256 wad) { function _getMakerVaultDebt(uint256 _vaultId) view returns (uint256 wad) {
IMcdManager manager = IMcdManager(MCD_MANAGER); IMcdManager manager = IMcdManager(MCD_MANAGER);
@ -48,6 +54,59 @@ function _getMakerVaultCollateralBalance(uint256 _vaultId)
return ink; return ink;
} }
function _isVaultWillBeSafe(
uint256 _vaultId,
uint256 _amtToBorrow,
uint256 _colToDeposit
) view returns (bool) {
require(_vaultId != 0, "_isVaultWillBeSafe: invalid vault id.");
IMcdManager manager = IMcdManager(MCD_MANAGER);
(bytes32 ilk, address urn) = _getVaultData(manager, _vaultId);
ITokenJoinInterface tokenJoinContract =
ITokenJoinInterface(InstaMapping(INSTA_MAPPING).gemJoinMapping(ilk));
IVat vat = IVat(manager.vat());
(, uint256 rate, uint256 spot, , ) = vat.ilks(ilk);
(uint256 ink, uint256 art) = vat.urns(ilk, urn);
uint256 dai = vat.dai(urn);
uint256 dink = _convertTo18(tokenJoinContract.dec(), _colToDeposit);
uint256 dart = _getBorrowAmt(_amtToBorrow, dai, rate);
ink = add(ink, dink);
art = add(art, dart);
uint256 tab = mul(rate, art);
return tab <= mul(ink, spot);
}
function _isNewVaultWillBeSafe(
string memory _colType,
uint256 _amtToBorrow,
uint256 _colToDeposit
) view returns (bool) {
IMcdManager manager = IMcdManager(MCD_MANAGER);
IVat vat = IVat(manager.vat());
bytes32 ilk = _stringToBytes32(_colType);
(, uint256 rate, uint256 spot, , ) = vat.ilks(ilk);
ITokenJoinInterface tokenJoinContract =
ITokenJoinInterface(InstaMapping(INSTA_MAPPING).gemJoinMapping(ilk));
uint256 ink = _convertTo18(tokenJoinContract.dec(), _colToDeposit);
uint256 art = _getBorrowAmt(_amtToBorrow, 0, rate);
uint256 tab = mul(rate, art);
return tab <= mul(ink, spot);
}
function _getVaultData(IMcdManager manager, uint256 vault) function _getVaultData(IMcdManager manager, uint256 vault)
view view
returns (bytes32 ilk, address urn) returns (bytes32 ilk, address urn)
@ -55,3 +114,12 @@ function _getVaultData(IMcdManager manager, uint256 vault)
ilk = manager.ilks(vault); ilk = manager.ilks(vault);
urn = manager.urns(vault); urn = manager.urns(vault);
} }
function _getBorrowAmt(
uint256 _amt,
uint256 _dai,
uint256 _rate
) pure returns (uint256 dart) {
dart = sub(mul(_amt, RAY), _dai) / _rate;
dart = mul(dart, _rate) < mul(_amt, RAY) ? dart + 1 : dart;
}

View File

@ -41,3 +41,7 @@ interface ConnectorInterface {
function name() external view returns (string memory); function name() external view returns (string memory);
} }
interface InstaMapping {
function gemJoinMapping(bytes32) external view returns (address);
}

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
interface ITokenJoinInterface {
function dec() external view returns (uint256);
}

19
contracts/vendor/Convert.sol vendored Normal file
View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.4;
import {RAY, add, sub, mul} from "./DSMath.sol";
function _stringToBytes32(string memory str)
pure
returns (bytes32 result)
{
require(bytes(str).length != 0, "string-empty");
assembly {
result := mload(add(str, 32))
}
}
function _convertTo18(uint256 _dec, uint256 _amt)
pure returns (uint256 amt) {
amt = mul(_amt, 10**(18 - _dec));
}

View File

@ -0,0 +1,27 @@
const { sleep } = require("@gelatonetwork/core");
module.exports = async (hre) => {
if (hre.network.name === "mainnet") {
console.log(
"Deploying ConditionIsDestVaultWillBeSafe to mainnet. Hit ctrl + c to abort"
);
await sleep(10000);
}
const { deployments } = hre;
const { deploy } = deployments;
const { deployer } = await hre.getNamedAccounts();
// the following will only deploy "ConditionIsDestVaultWillBeSafe"
// if the contract was never deployed or if the code changed since last deployment
await deploy("ConditionIsDestVaultWillBeSafe", {
from: deployer,
gasPrice: hre.network.config.gasPrice,
log: hre.network.name === "mainnet" ? true : false,
});
};
module.exports.skip = async (hre) => {
return hre.network.name === "mainnet" ? true : false;
};
module.exports.tags = ["ConditionIsDestVaultWillBeSafe"];

View File

@ -12,7 +12,7 @@ const { utils } = require("ethers");
const GelatoCoreLib = require("@gelatonetwork/core"); const GelatoCoreLib = require("@gelatonetwork/core");
const mainnetDeployments = require("./hardhat/config/mainnet-deployments"); const mainnetDeployments = require("./tool/config/mainnet-deployments");
// Process Env Variables // Process Env Variables
require("dotenv").config(); require("dotenv").config();
@ -55,7 +55,7 @@ module.exports = {
// timeout: 150000, // timeout: 150000,
forking: { forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
blockNumber: 11189230, blockNumber: 11310523,
}, },
// Custom // Custom
...mainnetDeployments, ...mainnetDeployments,

View File

@ -20,9 +20,11 @@ describe("Gas Measurements: Full Debt Bridge From Maker ETH-A to ETH-B", functio
// Payload Params for ConnectGelatoFullDebtBridgeFromMaker and ConditionMakerVaultUnsafe // Payload Params for ConnectGelatoFullDebtBridgeFromMaker and ConditionMakerVaultUnsafe
let vaultAId; let vaultAId;
let vaultBId;
let conditionMakerVaultUnsafeObj; let conditionMakerVaultUnsafeObj;
let conditionDebtBridgeIsAffordableObj; let conditionDebtBridgeIsAffordableObj;
let conditionIsDestVaultWillBeSafe;
// For TaskSpec and for Task // For TaskSpec and for Task
let gelatoDebtBridgeSpells = []; let gelatoDebtBridgeSpells = [];
@ -52,6 +54,7 @@ describe("Gas Measurements: Full Debt Bridge From Maker ETH-A to ETH-B", functio
wallets = result.wallets; wallets = result.wallets;
contracts = result.contracts; contracts = result.contracts;
vaultAId = result.vaultAId; vaultAId = result.vaultAId;
vaultBId = result.vaultBId;
gelatoDebtBridgeSpells = result.spells; gelatoDebtBridgeSpells = result.spells;
ABI = result.ABI; ABI = result.ABI;
@ -81,10 +84,20 @@ describe("Gas Measurements: Full Debt Bridge From Maker ETH-A to ETH-B", functio
), ),
}); });
conditionIsDestVaultWillBeSafe = new GelatoCoreLib.Condition({
inst: contracts.conditionIsDestVaultWillBeSafe.address,
data: await contracts.conditionIsDestVaultWillBeSafe.getConditionData(
vaultAId,
vaultBId,
"ETH-B"
),
});
refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({ refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({
conditions: [ conditions: [
conditionMakerVaultUnsafeObj, conditionMakerVaultUnsafeObj,
conditionDebtBridgeIsAffordableObj, conditionDebtBridgeIsAffordableObj,
conditionIsDestVaultWillBeSafe,
], ],
actions: gelatoDebtBridgeSpells, actions: gelatoDebtBridgeSpells,
}); });

View File

@ -41,6 +41,7 @@ module.exports = async function (
conditions: [ conditions: [
contracts.conditionMakerVaultUnsafe.address, contracts.conditionMakerVaultUnsafe.address,
contracts.conditionDebtBridgeIsAffordable.address, contracts.conditionDebtBridgeIsAffordable.address,
contracts.conditionIsDestVaultWillBeSafe.address,
], ],
actions: spells, actions: spells,
gasPriceCeil, gasPriceCeil,

View File

@ -5,7 +5,6 @@ const provideFunds = require("../../../../../helpers/services/gelato/provideFund
const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor"); const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor");
const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA"); const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA");
const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA"); const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA");
const addETHBGemJoinMapping = require("../../../../../helpers/services/maker/addETHBGemJoinMapping");
const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp"); const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp");
const createVaultForETHB = require("../../../../../helpers/services/maker/createVaultForETHB"); const createVaultForETHB = require("../../../../../helpers/services/maker/createVaultForETHB");
const mockGetSpellsETHAETHBWithVaultCreation = require("./services/getSpells-ETHA-ETHB-With-Vault-Creation.mock"); const mockGetSpellsETHAETHBWithVaultCreation = require("./services/getSpells-ETHA-ETHB-With-Vault-Creation.mock");
@ -38,11 +37,6 @@ module.exports = async function (mockRoute) {
contracts.instaIndex, contracts.instaIndex,
contracts.instaList contracts.instaList
); );
await addETHBGemJoinMapping(
wallets.userWallet,
contracts.instaMapping,
contracts.instaMaster
);
const vaultAId = await initializeMakerCdp( const vaultAId = await initializeMakerCdp(
wallets.userAddress, wallets.userAddress,
contracts.DAI, contracts.DAI,

View File

@ -113,6 +113,10 @@ module.exports = async function () {
"MockConnectGelatoDataFullRefinanceMaker" "MockConnectGelatoDataFullRefinanceMaker"
); );
const conditionIsDestVaultWillBeSafe = await ethers.getContract(
"ConditionIsDestVaultWillBeSafe"
);
return { return {
connectGelato, connectGelato,
connectMaker, connectMaker,
@ -141,5 +145,6 @@ module.exports = async function () {
conditionDebtBridgeIsAffordable, conditionDebtBridgeIsAffordable,
mockDebtBridgeETHBExecutor, mockDebtBridgeETHBExecutor,
mockConnectGelatoDataFullRefinanceMaker, mockConnectGelatoDataFullRefinanceMaker,
conditionIsDestVaultWillBeSafe,
}; };
}; };

View File

@ -102,11 +102,21 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B with vault creat
), ),
}); });
const conditionIsDestVaultWillBeSafe = new GelatoCoreLib.Condition({
inst: contracts.conditionIsDestVaultWillBeSafe.address,
data: await contracts.conditionIsDestVaultWillBeSafe.getConditionData(
vaultAId,
0,
"ETH-B"
),
});
// ======= GELATO TASK SETUP ====== // ======= GELATO TASK SETUP ======
const refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({ const refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({
conditions: [ conditions: [
conditionMakerVaultUnsafeObj, conditionMakerVaultUnsafeObj,
conditionDebtBridgeIsAffordableObj, conditionDebtBridgeIsAffordableObj,
conditionIsDestVaultWillBeSafe,
], ],
actions: gelatoDebtBridgeSpells, actions: gelatoDebtBridgeSpells,
}); });

View File

@ -23,6 +23,7 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B", function () {
// Payload Params for ConnectGelatoFullDebtBridgeFromMaker and ConditionMakerVaultUnsafe // Payload Params for ConnectGelatoFullDebtBridgeFromMaker and ConditionMakerVaultUnsafe
let vaultAId; let vaultAId;
let vaultBId;
// For TaskSpec and for Task // For TaskSpec and for Task
let gelatoDebtBridgeSpells = []; let gelatoDebtBridgeSpells = [];
@ -39,6 +40,7 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B", function () {
wallets = result.wallets; wallets = result.wallets;
contracts = result.contracts; contracts = result.contracts;
vaultAId = result.vaultAId; vaultAId = result.vaultAId;
vaultBId = result.vaultBId;
gelatoDebtBridgeSpells = result.spells; gelatoDebtBridgeSpells = result.spells;
ABI = result.ABI; ABI = result.ABI;
@ -102,11 +104,21 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B", function () {
), ),
}); });
const conditionIsDestVaultWillBeSafe = new GelatoCoreLib.Condition({
inst: contracts.conditionIsDestVaultWillBeSafe.address,
data: await contracts.conditionIsDestVaultWillBeSafe.getConditionData(
vaultAId,
vaultBId,
"ETH-B"
),
});
// ======= GELATO TASK SETUP ====== // ======= GELATO TASK SETUP ======
const refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({ const refinanceFromEthAToBIfVaultUnsafe = new GelatoCoreLib.Task({
conditions: [ conditions: [
conditionMakerVaultUnsafeObj, conditionMakerVaultUnsafeObj,
conditionDebtBridgeIsAffordableObj, conditionDebtBridgeIsAffordableObj,
conditionIsDestVaultWillBeSafe,
], ],
actions: gelatoDebtBridgeSpells, actions: gelatoDebtBridgeSpells,
}); });

View File

@ -35,6 +35,7 @@ module.exports = async function (wallets, contracts, constants, vaultId) {
conditions: [ conditions: [
contracts.conditionMakerVaultUnsafe.address, contracts.conditionMakerVaultUnsafe.address,
contracts.conditionDebtBridgeIsAffordable.address, contracts.conditionDebtBridgeIsAffordable.address,
contracts.conditionIsDestVaultWillBeSafe.address,
], ],
actions: spells, actions: spells,
gasPriceCeil, gasPriceCeil,

View File

@ -41,6 +41,7 @@ module.exports = async function (
conditions: [ conditions: [
contracts.conditionMakerVaultUnsafe.address, contracts.conditionMakerVaultUnsafe.address,
contracts.conditionDebtBridgeIsAffordable.address, contracts.conditionDebtBridgeIsAffordable.address,
contracts.conditionIsDestVaultWillBeSafe.address,
], ],
actions: spells, actions: spells,
gasPriceCeil, gasPriceCeil,

View File

@ -6,7 +6,6 @@ const provideFunds = require("../../../../../helpers/services/gelato/provideFund
const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor"); const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor");
const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA"); const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA");
const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA"); const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA");
const addETHBGemJoinMapping = require("../../../../../helpers/services/maker/addETHBGemJoinMapping");
const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp"); const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp");
const createVaultForETHB = require("../../../../../helpers/services/maker/createVaultForETHB"); const createVaultForETHB = require("../../../../../helpers/services/maker/createVaultForETHB");
const getSpellsEthAEthB = require("./services/getSpells-ETHA-ETHB"); const getSpellsEthAEthB = require("./services/getSpells-ETHA-ETHB");
@ -40,11 +39,6 @@ module.exports = async function () {
contracts.instaIndex, contracts.instaIndex,
contracts.instaList contracts.instaList
); );
await addETHBGemJoinMapping(
wallets.userWallet,
contracts.instaMapping,
contracts.instaMaster
);
const vaultAId = await initializeMakerCdp( const vaultAId = await initializeMakerCdp(
wallets.userAddress, wallets.userAddress,
contracts.DAI, contracts.DAI,

View File

@ -6,7 +6,6 @@ const provideFunds = require("../../../../../helpers/services/gelato/provideFund
const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor"); const providerAssignsExecutor = require("../../../../../helpers/services/gelato/providerAssignsExecutor");
const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA"); const addProviderModuleDSA = require("../../../../../helpers/services/gelato/addProviderModuleDSA");
const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA"); const createDSA = require("../../../../../helpers/services/InstaDapp/createDSA");
const addETHBGemJoinMapping = require("../../../../../helpers/services/maker/addETHBGemJoinMapping");
const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp"); const initializeMakerCdp = require("../../../../../helpers/services/maker/initializeMakerCdp");
const getSpellsEthAEthBWithVaultCreation = require("./services/getSpells-ETHA-ETHB-With-Vault-Creation"); const getSpellsEthAEthBWithVaultCreation = require("./services/getSpells-ETHA-ETHB-With-Vault-Creation");
const getABI = require("../../../../../helpers/services/getABI"); const getABI = require("../../../../../helpers/services/getABI");
@ -39,11 +38,6 @@ module.exports = async function () {
contracts.instaIndex, contracts.instaIndex,
contracts.instaList contracts.instaList
); );
await addETHBGemJoinMapping(
wallets.userWallet,
contracts.instaMapping,
contracts.instaMaster
);
const vaultAId = await initializeMakerCdp( const vaultAId = await initializeMakerCdp(
wallets.userAddress, wallets.userAddress,
contracts.DAI, contracts.DAI,

View File

@ -147,7 +147,7 @@ describe("ConditionDebtBridgeIsAffordable Unit Test", function () {
it("#2: ok should return OK when the gas fees not exceed a define amount", async function () { it("#2: ok should return OK when the gas fees not exceed a define amount", async function () {
const conditionData = await conditionDebtBridgeIsAffordable.getConditionData( const conditionData = await conditionDebtBridgeIsAffordable.getConditionData(
cdpId, cdpId,
ethers.utils.parseUnits("10", 15) ethers.utils.parseUnits("10", 16)
); );
expect( expect(

View File

@ -0,0 +1,306 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { deployments, ethers } = hre;
// #region Contracts ABI
const ConnectMaker = require("../../../pre-compiles/ConnectMaker.json");
const GetCdps = require("../../../pre-compiles/GetCdps.json");
const DssCdpManager = require("../../../pre-compiles/DssCdpManager.json");
const InstaList = require("../../../pre-compiles/InstaList.json");
const InstaAccount = require("../../../pre-compiles/InstaAccount.json");
const InstaIndex = require("../../../pre-compiles/InstaIndex.json");
const Vat = require("../../../artifacts/contracts/interfaces/dapps/Maker/IVat.sol/IVat.json");
const IERC20 = require("../../../pre-compiles/IERC20.json");
// #endregion
describe("ConditionIsDestVaultWillBeSafe Unit Test", function () {
this.timeout(0);
if (hre.network.name !== "hardhat") {
console.error("Test Suite is meant to be run on hardhat only");
process.exit(1);
}
let userWallet;
let userAddress;
let getCdps;
let dssCdpManager;
let instaList;
let instaIndex;
let DAI;
let vat;
let conditionIsDestVaultWillBeSafe;
let dsa;
let cdpId;
let ilk;
let ethBIlk;
let amountToBorrow;
beforeEach(async function () {
// Deploy contract dependencies
await deployments.fixture();
// Get Test Wallet for local testnet
[userWallet] = await ethers.getSigners();
userAddress = await userWallet.getAddress();
// Hardhat default accounts prefilled with 100 ETH
expect(await userWallet.getBalance()).to.be.gt(
ethers.utils.parseEther("10")
);
instaIndex = await ethers.getContractAt(
InstaIndex.abi,
hre.network.config.InstaIndex
);
instaList = await ethers.getContractAt(
InstaList.abi,
hre.network.config.InstaList
);
getCdps = await ethers.getContractAt(
GetCdps.abi,
hre.network.config.GetCdps
);
dssCdpManager = await ethers.getContractAt(
DssCdpManager.abi,
hre.network.config.DssCdpManager
);
vat = new ethers.Contract(await dssCdpManager.vat(), Vat.abi, userWallet);
DAI = await ethers.getContractAt(IERC20.abi, hre.network.config.DAI);
// ========== Test Setup ============
conditionIsDestVaultWillBeSafe = await ethers.getContract(
"ConditionIsDestVaultWillBeSafe"
);
// Create DeFi Smart Account
const dsaAccountCount = await instaList.accounts();
await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit(
instaIndex,
"LogAccountCreated"
);
const dsaID = dsaAccountCount.add(1);
await expect(await instaList.accounts()).to.be.equal(dsaID);
// Instantiate the DSA
dsa = await ethers.getContractAt(
InstaAccount.abi,
await instaList.accountAddr(dsaID)
);
// Create/Deposit/Borrow a Vault
const openVault = await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "open",
inputs: ["ETH-A"],
});
await dsa.cast([hre.network.config.ConnectMaker], [openVault], userAddress);
let cdps = await getCdps.getCdpsAsc(dssCdpManager.address, dsa.address);
cdpId = String(cdps.ids[0]);
expect(cdps.ids[0].isZero()).to.be.false;
await dsa.cast(
[hre.network.config.ConnectMaker],
[
await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "deposit",
inputs: [cdpId, ethers.utils.parseEther("10"), 0, 0],
}),
],
userAddress,
{
value: ethers.utils.parseEther("10"),
}
);
await dsa.cast(
[hre.network.config.ConnectMaker],
[
await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "borrow",
inputs: [cdpId, ethers.utils.parseUnits("1000", 18), 0, 0],
}),
],
userAddress
);
expect(await DAI.balanceOf(dsa.address)).to.be.equal(
ethers.utils.parseEther("1000")
);
ethBIlk = ethers.utils.formatBytes32String("ETH-B");
ilk = await vat.ilks(ethBIlk);
amountToBorrow = ethers.utils.parseUnits("100", 18);
});
it("#1: ok should return DebtBridgeNotAffordable when the gas fees exceed a define amount", async function () {
const conditionData = await conditionIsDestVaultWillBeSafe.getConditionData(
cdpId,
0,
"ETH-B"
);
expect(
await conditionIsDestVaultWillBeSafe.ok(0, conditionData, 0)
).to.be.equal("OK");
});
it("#2: New Vault Case : isDestVaultWillBeSafe should return false when col is lower than borrow amount / spot", async function () {
var amountOfColToDepo = amountToBorrow
.mul(ilk[1])
.div(ethers.utils.parseUnits("1", 27));
amountOfColToDepo = amountOfColToDepo
.sub(amountOfColToDepo.div(ethers.utils.parseUnits("10", 0)))
.mul(ethers.utils.parseUnits("1", 27))
.div(ilk[2]);
expect(
await conditionIsDestVaultWillBeSafe.isDestVaultWillBeSafe(
0,
amountToBorrow,
amountOfColToDepo,
"ETH-B"
)
).to.be.false;
});
it("#3: New Vault Case : isDestVaultWillBeSafe should return true when col is greater than borrow amount / spot", async function () {
let amountOfColToDepo = amountToBorrow
.mul(ilk[1])
.div(ethers.utils.parseUnits("1", 27));
amountOfColToDepo = amountOfColToDepo
.add(amountOfColToDepo.div(ethers.utils.parseUnits("10", 0)))
.mul(ethers.utils.parseUnits("1", 27))
.div(ilk[2]);
expect(
await conditionIsDestVaultWillBeSafe.isDestVaultWillBeSafe(
0,
amountToBorrow,
amountOfColToDepo,
"ETH-B"
)
).to.be.true;
});
it("#4: Old Vault Case : isDestVaultWillBeSafe should return false when col is lower than borrow amount / spot", async function () {
const openVault = await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "open",
inputs: ["ETH-B"],
});
await dsa.cast([hre.network.config.ConnectMaker], [openVault], userAddress);
const cdpIdB = String(
(await getCdps.getCdpsAsc(dssCdpManager.address, dsa.address)).ids[1]
);
let amountOfColToDepo = amountToBorrow
.mul(ilk[1])
.div(ethers.utils.parseUnits("1", 27));
amountOfColToDepo = amountOfColToDepo
.sub(amountOfColToDepo.div(ethers.utils.parseUnits("10", 0)))
.mul(ethers.utils.parseUnits("1", 27))
.div(ilk[2]);
expect(
await conditionIsDestVaultWillBeSafe.isDestVaultWillBeSafe(
cdpIdB,
amountToBorrow,
amountOfColToDepo,
"ETH-B"
)
).to.be.false;
});
it("#5: Old Vault Case : isDestVaultWillBeSafe should return true when col is lower than borrow amount / spot", async function () {
const openVault = await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "open",
inputs: ["ETH-B"],
});
await dsa.cast([hre.network.config.ConnectMaker], [openVault], userAddress);
const cdpIdB = String(
(await getCdps.getCdpsAsc(dssCdpManager.address, dsa.address)).ids[1]
);
let amountOfColToDepo = amountToBorrow
.mul(ilk[1])
.div(ethers.utils.parseUnits("1", 27));
amountOfColToDepo = amountOfColToDepo
.add(amountOfColToDepo.div(ethers.utils.parseUnits("10", 0)))
.mul(ethers.utils.parseUnits("1", 27))
.div(ilk[2]);
expect(
await conditionIsDestVaultWillBeSafe.isDestVaultWillBeSafe(
cdpIdB,
amountToBorrow,
amountOfColToDepo,
"ETH-B"
)
).to.be.true;
});
it("#6: Old Vault Case with existing deposit : isDestVaultWillBeSafe should return true when col is lower than borrow amount / spot due to initial deposit on Vault B", async function () {
const openVault = await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "open",
inputs: ["ETH-B"],
});
await dsa.cast([hre.network.config.ConnectMaker], [openVault], userAddress);
const cdpIdB = String(
(await getCdps.getCdpsAsc(dssCdpManager.address, dsa.address)).ids[1]
);
let amountOfColToDepo = amountToBorrow
.mul(ilk[1])
.div(ethers.utils.parseUnits("1", 27));
const tenPercentOfAmountOfColToDepo = amountOfColToDepo.div(
ethers.utils.parseUnits("10", 0)
);
amountOfColToDepo = amountOfColToDepo
.sub(tenPercentOfAmountOfColToDepo)
.mul(ethers.utils.parseUnits("1", 27))
.div(ilk[2]);
// Deposit For ETH-B Vault
await dsa.cast(
[hre.network.config.ConnectMaker],
[
await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "deposit",
inputs: [cdpIdB, tenPercentOfAmountOfColToDepo, 0, 0],
}),
],
userAddress,
{
value: tenPercentOfAmountOfColToDepo,
}
);
expect(
await conditionIsDestVaultWillBeSafe.isDestVaultWillBeSafe(
cdpIdB,
amountToBorrow,
amountOfColToDepo,
"ETH-B"
)
).to.be.true;
});
});

View File

@ -67,9 +67,7 @@ describe("FGelatoDebtBridge Unit Tests", function () {
it("getFlashLoanRoute should revert with FGelatoDebtBridge._getFlashLoanRoute: illiquid", async function () { it("getFlashLoanRoute should revert with FGelatoDebtBridge._getFlashLoanRoute: illiquid", async function () {
const rData = await instaPoolResolver.getTokenLimit(DAI); const rData = await instaPoolResolver.getTokenLimit(DAI);
const daiAmtToBorrow = ethers.utils const daiAmtToBorrow = ethers.utils.parseUnits("1000", 18).add(rData.aave);
.parseUnits("1000", 18)
.add(rData.compound);
await expect( await expect(
fGelatoDebtBridgeMock.getFlashLoanRoute(DAI, daiAmtToBorrow) fGelatoDebtBridgeMock.getFlashLoanRoute(DAI, daiAmtToBorrow)