mirror of
https://github.com/Instadapp/Gelato-automations.git
synced 2024-07-29 22:28:07 +00:00
Unit testing new smart contract.
This commit is contained in:
parent
e6a37987b8
commit
d04f327159
|
@ -25,6 +25,7 @@ module.exports = {
|
|||
unlocked_accounts: [INSTA_MASTER],
|
||||
// Custom
|
||||
GelatoCore: "0x1d681d76ce96E4d70a88A00EBbcfc1E47808d0b8",
|
||||
GelatoGasPriceOracle: "0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C",
|
||||
InstaMaster: INSTA_MASTER,
|
||||
InstaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
|
||||
InstaList: "0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb",
|
||||
|
@ -37,9 +38,11 @@ module.exports = {
|
|||
ConnectCompound: "0x07F81230d73a78f63F0c2A3403AD281b067d28F8",
|
||||
ConnectInstaPool: "0xCeF5f3c402d4fef76A038e89a4357176963e1464",
|
||||
MakerResolver: "0x0A7008B38E7015F8C36A49eEbc32513ECA8801E5",
|
||||
CompoundResolver: "0x1f22D77365d8BFE3b901C33C83C01B584F946617",
|
||||
DAI: "0x6b175474e89094c44da98b954eedeac495271d0f",
|
||||
DAI_UNISWAP: "0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667",
|
||||
CDAI: "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643",
|
||||
CETH: "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5",
|
||||
DssCdpManager: "0x5ef30b9986345249bc32d8928B7ee64DE9435E39",
|
||||
GetCdps: "0x36a724Bd100c39f0Ea4D3A20F7097eE01A8Ff573",
|
||||
ProviderModuleDSA: "0x0C25452d20cdFeEd2983fa9b9b9Cf4E81D6f2fE2",
|
||||
|
|
|
@ -293,7 +293,7 @@ contract ConnectGelatoDebtBridge is ConnectGelatoDebtBridgeResolver {
|
|||
// Constant name must be in capitalized SNAKE_CASE
|
||||
// solhint-disable-next-line
|
||||
string public constant override name = "GelatoDebtBridge-v1.0";
|
||||
uint256 public constant GASLIMIT = 2000000; // To Define
|
||||
uint256 public constant GASLIMIT = 1933090 + (19331 * 2); // 1933080 + ~2% (Estimated Value)
|
||||
address public immutable oracleAggregator;
|
||||
|
||||
constructor(uint256 _iD, address _oracleAggregator) public {
|
||||
|
@ -315,7 +315,7 @@ contract ConnectGelatoDebtBridge is ConnectGelatoDebtBridgeResolver {
|
|||
string memory _pair,
|
||||
uint256 _getID,
|
||||
uint256 _setID
|
||||
) external {
|
||||
) external payable {
|
||||
(
|
||||
uint256 paybackAmount,
|
||||
uint256 collateralToWithdraw,
|
||||
|
|
|
@ -59,7 +59,7 @@ contract ConnectGelatoProviderPayment is ConnectGelatoProviderPaymentHelper {
|
|||
uint256 _amt,
|
||||
uint256 _getID,
|
||||
uint256 _setID
|
||||
) public {
|
||||
) public payable {
|
||||
// Desable linter for too long require statement
|
||||
// solhint-disable-next-line
|
||||
require(
|
||||
|
|
37
contracts/Mocks/ConnectGelatoDebtBridgeMock.sol
Normal file
37
contracts/Mocks/ConnectGelatoDebtBridgeMock.sol
Normal file
|
@ -0,0 +1,37 @@
|
|||
pragma solidity 0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../ConnectGelatoDEbtBridge.sol";
|
||||
|
||||
contract ConnectGelatoDebtBridgeMock is ConnectGelatoDebtBridge {
|
||||
constructor(uint256 _iD, address _oracleAggregator)
|
||||
public
|
||||
ConnectGelatoDebtBridge(_iD, _oracleAggregator)
|
||||
{}
|
||||
|
||||
function wcollateralToWithdraw(
|
||||
uint256 _p1LiqRatio,
|
||||
uint256 _p2LiqRatio,
|
||||
uint256 _col,
|
||||
uint256 _bor,
|
||||
uint256 _colPrice
|
||||
) public pure returns (uint256) {
|
||||
return
|
||||
_wcollateralToWithdraw(
|
||||
_p1LiqRatio,
|
||||
_p2LiqRatio,
|
||||
_col,
|
||||
_bor,
|
||||
_colPrice
|
||||
);
|
||||
}
|
||||
|
||||
function wborrowedTokenToPayback(
|
||||
uint256 _p1LiqRatio,
|
||||
uint256 _p2LiqRatio,
|
||||
uint256 _col,
|
||||
uint256 _bor
|
||||
) public pure returns (uint256) {
|
||||
return _wborrowedTokenToPayback(_p1LiqRatio, _p2LiqRatio, _col, _bor);
|
||||
}
|
||||
}
|
|
@ -10,9 +10,9 @@ interface IMakerPriceFeed {
|
|||
}
|
||||
|
||||
contract OracleAggregatorStorage {
|
||||
mapping(string => address) internal _makerOracle;
|
||||
mapping(string => address) internal _compoundOracle;
|
||||
mapping(string => address) internal _chainlinkOracle;
|
||||
mapping(string => address) public makerOracle;
|
||||
mapping(string => address) public compoundOracle;
|
||||
mapping(string => address) public chainlinkOracle;
|
||||
}
|
||||
|
||||
// 0x729D19f657BD0614b4985Cf1D82531c67569197B for ETH/USD medianizer it return value in wad standard.
|
||||
|
@ -37,10 +37,10 @@ contract OracleAggregator is OracleAggregatorStorage, Ownable, DSMath {
|
|||
// Desable linter for too long require statement
|
||||
// solhint-disable-next-line
|
||||
require(
|
||||
_makerOracle[_pair] == address(0x0),
|
||||
makerOracle[_pair] == address(0x0),
|
||||
"OracleAggregator.Maker: Oracle already set."
|
||||
);
|
||||
_makerOracle[_pair] = _oracleAddress;
|
||||
makerOracle[_pair] = _oracleAddress;
|
||||
}
|
||||
|
||||
function getMakerTokenPrice(string memory _pair)
|
||||
|
@ -48,9 +48,15 @@ contract OracleAggregator is OracleAggregatorStorage, Ownable, DSMath {
|
|||
view
|
||||
returns (uint256)
|
||||
{
|
||||
// Desable linter for too long require statement
|
||||
// solhint-disable-next-line
|
||||
require(
|
||||
makerOracle[_pair] != address(0x0),
|
||||
"OracleAggregator.getMakerTokenPrice: CurrencyPairNotSupported."
|
||||
);
|
||||
if (mockMode) {
|
||||
return mockValue;
|
||||
}
|
||||
return uint256(IMakerPriceFeed(_makerOracle[_pair]).read());
|
||||
return uint256(IMakerPriceFeed(makerOracle[_pair]).read());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,26 +3,7 @@
|
|||
"abi": [
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "_acceptAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address payable",
|
||||
"name": "newPendingAdmin",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "_setPendingAdmin",
|
||||
"name": "accrueInterest",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
|
@ -285,6 +266,19 @@
|
|||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalBorrows",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalBorrowsCurrent",
|
||||
|
@ -298,6 +292,32 @@
|
|||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalReserves",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
|
|
22
pre-compiles/GelatoGasPriceOracle.json
Normal file
22
pre-compiles/GelatoGasPriceOracle.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"contractName": "GelatoGasPriceOracle",
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "latestAnswer",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int256",
|
||||
"name": "",
|
||||
"type": "int256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"bytecode": "0x",
|
||||
"deployedBytecode": "0x",
|
||||
"linkReferences": {},
|
||||
"deployedLinkReferences": {}
|
||||
}
|
260
pre-compiles/InstaCompoundResolver.json
Normal file
260
pre-compiles/InstaCompoundResolver.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -21,13 +21,86 @@ const DssCdpManager = require("../pre-compiles/DssCdpManager.json");
|
|||
const GetCdps = require("../pre-compiles/GetCdps.json");
|
||||
const IERC20 = require("../pre-compiles/IERC20.json");
|
||||
const CTokenInterface = require("../pre-compiles/CTokenInterface.json");
|
||||
const GelatoGasPriceOracle = require("../pre-compiles/GelatoGasPriceOracle.json");
|
||||
const CompoundResolver = require("../pre-compiles/InstaCompoundResolver.json");
|
||||
|
||||
const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
const GAS_LIMIT = "4000000";
|
||||
const GAS_PRICE_CEIL = ethers.utils.parseUnits("1000", "gwei");
|
||||
const WAD = ethers.utils.parseUnits("1", 18);
|
||||
|
||||
// #endregion
|
||||
|
||||
//#region Mock Math Function
|
||||
|
||||
let wdiv = (x, y) => {
|
||||
return x.mul(WAD).add(y.div(2)).div(y);
|
||||
};
|
||||
|
||||
let wmul = (x, y) => {
|
||||
return x.mul(y).add(WAD.div(2)).div(WAD);
|
||||
};
|
||||
|
||||
let wcollateralToWithdraw = (
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
borrowedToken,
|
||||
collateralPrice
|
||||
) => {
|
||||
//#region CALCULATION REPLICATION
|
||||
|
||||
let expectedColToWithdraw = wmul(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, wantedLiquidationRatioOnProtocol2),
|
||||
borrowedToken
|
||||
); // doc ref : c_r x comp_r x d_2
|
||||
expectedColToWithdraw = expectedColToWithdraw.sub(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, collateral)
|
||||
); // doc ref : c_r x comp_r x d_2 - c_r x e_2
|
||||
expectedColToWithdraw = wdiv(
|
||||
expectedColToWithdraw,
|
||||
wantedLiquidationRatioOnProtocol2.sub(wantedLiquidationRatioOnProtocol1)
|
||||
); // doc ref : (c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r)
|
||||
expectedColToWithdraw = collateral.sub(expectedColToWithdraw); // doc ref : e_2 - ((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
|
||||
// Extra step to convert back to col type
|
||||
expectedColToWithdraw = wdiv(expectedColToWithdraw, collateralPrice);
|
||||
|
||||
//#endregion
|
||||
return expectedColToWithdraw;
|
||||
};
|
||||
|
||||
let wborrowedTokenToPayback = (
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
borrowedToken
|
||||
) => {
|
||||
//#region CALCULATION REPLICATION
|
||||
|
||||
let expectedBorToPayBack = wmul(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, wantedLiquidationRatioOnProtocol2),
|
||||
borrowedToken
|
||||
); // doc ref : c_r x comp_r x d_2
|
||||
expectedBorToPayBack = expectedBorToPayBack.sub(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, collateral)
|
||||
); // doc ref : c_r x comp_r x d_2 - c_r x e_2
|
||||
expectedBorToPayBack = wdiv(
|
||||
expectedBorToPayBack,
|
||||
wantedLiquidationRatioOnProtocol2.sub(wantedLiquidationRatioOnProtocol1)
|
||||
); // doc ref : (c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r)
|
||||
expectedBorToPayBack = wmul(
|
||||
wdiv(ethers.utils.parseUnits("1", 18), wantedLiquidationRatioOnProtocol1),
|
||||
expectedBorToPayBack
|
||||
); // doc ref : (1/c_r)((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
expectedBorToPayBack = borrowedToken.sub(expectedBorToPayBack); // doc ref : d_2 - (1/c_r)((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
|
||||
//#endregion
|
||||
return expectedBorToPayBack;
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
describe("Debt Bridge with External Provider", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
|
@ -53,8 +126,11 @@ describe("Debt Bridge with External Provider", function () {
|
|||
let daiToken;
|
||||
let gelatoCore;
|
||||
let cDaiToken;
|
||||
let cEthToken;
|
||||
let instaMaster;
|
||||
let instaConnectors;
|
||||
let gelatoGasPriceOracle;
|
||||
let compoundResolver;
|
||||
|
||||
// Contracts to deploy and use for local testing
|
||||
let conditionMakerVaultIsSafe;
|
||||
|
@ -126,10 +202,22 @@ describe("Debt Bridge with External Provider", function () {
|
|||
CTokenInterface.abi,
|
||||
bre.network.config.CDAI
|
||||
);
|
||||
cEthToken = await ethers.getContractAt(
|
||||
CTokenInterface.abi,
|
||||
bre.network.config.CETH
|
||||
);
|
||||
instaConnectors = await ethers.getContractAt(
|
||||
InstaConnector.abi,
|
||||
bre.network.config.InstaConnectors
|
||||
);
|
||||
gelatoGasPriceOracle = await ethers.getContractAt(
|
||||
GelatoGasPriceOracle.abi,
|
||||
bre.network.config.GelatoGasPriceOracle
|
||||
);
|
||||
compoundResolver = await ethers.getContractAt(
|
||||
CompoundResolver.abi,
|
||||
bre.network.config.CompoundResolver
|
||||
);
|
||||
// instaEvent = await ethers.getContractAt(
|
||||
// InstaEvent.abi,
|
||||
// bre.network.config.InstaEvent
|
||||
|
@ -449,7 +537,7 @@ describe("Debt Bridge with External Provider", function () {
|
|||
//#endregion
|
||||
});
|
||||
|
||||
it("Use Maker Compound refinancing if the maker vault become unsafe after a market move.", async function () {
|
||||
it("#1: Use Maker Compound refinancing if the maker vault become unsafe after a market move.", async function () {
|
||||
// User Actions
|
||||
// Step 1 : User create a DeFi Smart Account
|
||||
// Step 2 : User open a Vault, put some ether on it and borrow some dai
|
||||
|
@ -566,6 +654,10 @@ describe("Debt Bridge with External Provider", function () {
|
|||
// It will be done through a algorithm that will optimize the
|
||||
// total borrow rate.
|
||||
|
||||
let wantedLiquidationRatioOnProtocol1 = ethers.utils.parseUnits("3", 18);
|
||||
let wantedLiquidationRatioOnProtocol2 = ethers.utils.parseUnits("19", 17);
|
||||
let currencyPair = "ETH/USD";
|
||||
|
||||
const debtBridgeCondition = new GelatoCoreLib.Condition({
|
||||
inst: conditionMakerVaultIsSafe.address,
|
||||
data: await conditionMakerVaultIsSafe.getConditionData(
|
||||
|
@ -585,9 +677,9 @@ describe("Debt Bridge with External Provider", function () {
|
|||
functionname: "debtBridgeMakerToCompound",
|
||||
inputs: [
|
||||
cdpId,
|
||||
ethers.utils.parseUnits("3", 18),
|
||||
ethers.utils.parseUnits("18", 17),
|
||||
"ETH/USD",
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
currencyPair,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
|
@ -748,7 +840,37 @@ describe("Debt Bridge with External Provider", function () {
|
|||
// will execute the user's task to make the user position safe
|
||||
// by a debt refinancing in compound.
|
||||
|
||||
//#region EXPECTED OUTCOME
|
||||
|
||||
let latestPrice = await oracleAggregator.getMakerTokenPrice(currencyPair);
|
||||
let fees = ethers.utils
|
||||
.parseUnits("2000000", 0)
|
||||
.mul(await gelatoGasPriceOracle.latestAnswer());
|
||||
let debt = await connectGelatoDebtBridge.getMakerVaultDebt(cdpId);
|
||||
let collateral = wmul(
|
||||
await connectGelatoDebtBridge.getMakerVaultCollateralBalance(cdpId),
|
||||
latestPrice
|
||||
).sub(fees);
|
||||
|
||||
let expectedColWithdrawAmount = wcollateralToWithdraw(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
debt,
|
||||
latestPrice
|
||||
);
|
||||
|
||||
let expectedBorAmountToPayBack = wborrowedTokenToPayback(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
debt
|
||||
);
|
||||
|
||||
//#endregion
|
||||
|
||||
let providerBalanceBeforeExecution = await providerWallet.getBalance();
|
||||
|
||||
await expect(
|
||||
connectedGelatoCore.exec(taskReceipt, {
|
||||
gasPrice: gelatoGasPrice, // Exectutor must use gelatoGasPrice (Chainlink fast gwei)
|
||||
|
@ -757,15 +879,47 @@ describe("Debt Bridge with External Provider", function () {
|
|||
).to.emit(gelatoCore, "LogExecSuccess");
|
||||
|
||||
let providerBalanceAfterExecution = await providerWallet.getBalance();
|
||||
|
||||
expect(providerBalanceAfterExecution).to.be.gt(
|
||||
providerBalanceBeforeExecution
|
||||
);
|
||||
const amtOfBorrowedDAIOnCompound = (
|
||||
await cDaiToken.getAccountSnapshot(dsa.address)
|
||||
)[2];
|
||||
expect(amtOfBorrowedDAIOnCompound).to.be.lt(
|
||||
ethers.utils.parseUnits("1000", 18)
|
||||
); // Check the borrow amount
|
||||
|
||||
// compound position of DSA on cDai and cEth
|
||||
let compoundPosition = await compoundResolver.getCompoundData(dsa.address, [
|
||||
cDaiToken.address,
|
||||
cEthToken.address,
|
||||
]);
|
||||
|
||||
// https://compound.finance/docs/ctokens#exchange-rate
|
||||
// calculate cEth/ETH rate to convert back cEth to ETH
|
||||
// for comparing with the withdrew Ether to the deposited one.
|
||||
let exchangeRateCethToEth = (await cEthToken.getCash())
|
||||
.add(await cEthToken.totalBorrows())
|
||||
.sub(await cEthToken.totalReserves())
|
||||
.div(await cEthToken.totalSupply());
|
||||
|
||||
expect(
|
||||
expectedBorAmountToPayBack.sub(
|
||||
compoundPosition[0].borrowBalanceStoredUser
|
||||
)
|
||||
).to.be.gt(ethers.utils.parseUnits("1", 0));
|
||||
expect(
|
||||
expectedColWithdrawAmount.sub(
|
||||
compoundPosition[1].balanceOfUser.mul(exchangeRateCethToEth)
|
||||
)
|
||||
).to.be.gt(ethers.utils.parseUnits("1", 0));
|
||||
expect(
|
||||
expectedBorAmountToPayBack.sub(
|
||||
compoundPosition[0].borrowBalanceStoredUser
|
||||
)
|
||||
).to.be.lt(ethers.utils.parseUnits("1", 16));
|
||||
expect(
|
||||
expectedColWithdrawAmount.sub(
|
||||
compoundPosition[1].balanceOfUser.mul(exchangeRateCethToEth)
|
||||
)
|
||||
).to.be.lt(ethers.utils.parseUnits("1", 14));
|
||||
|
||||
// DSA contain 1000 DAI
|
||||
expect(await daiToken.balanceOf(dsa.address)).to.be.equal(
|
||||
ethers.utils.parseUnits("1000", 18)
|
||||
);
|
||||
|
|
182
test/3_ConditionMakerVaultIsSafe.test.js
Normal file
182
test/3_ConditionMakerVaultIsSafe.test.js
Normal file
|
@ -0,0 +1,182 @@
|
|||
const {expect} = require("chai");
|
||||
const bre = require("@nomiclabs/buidler");
|
||||
const {ethers} = bre;
|
||||
|
||||
// #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 IERC20 = require("../pre-compiles/IERC20.json");
|
||||
|
||||
// #endregion
|
||||
|
||||
describe("ConditionMakerVaultIsSafe gelato condition contract unit test", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
console.error("Test Suite is meant to be run on ganache only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let userWallet;
|
||||
let userAddress;
|
||||
|
||||
let getCdps;
|
||||
let dssCdpManager;
|
||||
let instaList;
|
||||
let instaIndex;
|
||||
let daiToken;
|
||||
|
||||
let conditionMakerVaultIsSafe;
|
||||
let oracleAggregator;
|
||||
|
||||
let cdpId;
|
||||
let dsa;
|
||||
|
||||
before(async function () {
|
||||
// Get Test Wallet for local testnet
|
||||
[userWallet] = await ethers.getSigners();
|
||||
userAddress = await userWallet.getAddress();
|
||||
|
||||
// Ganache default accounts prefilled with 100 ETH
|
||||
expect(await userWallet.getBalance()).to.be.gt(
|
||||
ethers.utils.parseEther("10")
|
||||
);
|
||||
|
||||
instaIndex = await ethers.getContractAt(
|
||||
InstaIndex.abi,
|
||||
bre.network.config.InstaIndex
|
||||
);
|
||||
instaList = await ethers.getContractAt(
|
||||
InstaList.abi,
|
||||
bre.network.config.InstaList
|
||||
);
|
||||
getCdps = await ethers.getContractAt(
|
||||
GetCdps.abi,
|
||||
bre.network.config.GetCdps
|
||||
);
|
||||
dssCdpManager = await ethers.getContractAt(
|
||||
DssCdpManager.abi,
|
||||
bre.network.config.DssCdpManager
|
||||
);
|
||||
daiToken = await ethers.getContractAt(IERC20.abi, bre.network.config.DAI);
|
||||
|
||||
// ========== Test Setup ============
|
||||
|
||||
const OracleAggregator = await ethers.getContractFactory(
|
||||
"OracleAggregator"
|
||||
);
|
||||
|
||||
oracleAggregator = await OracleAggregator.deploy();
|
||||
await oracleAggregator.deployed();
|
||||
|
||||
const ConditionMakerVaultIsSafe = await ethers.getContractFactory(
|
||||
"ConditionMakerVaultIsSafe"
|
||||
);
|
||||
|
||||
conditionMakerVaultIsSafe = await ConditionMakerVaultIsSafe.deploy(
|
||||
oracleAggregator.address
|
||||
);
|
||||
await conditionMakerVaultIsSafe.deployed();
|
||||
|
||||
// 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 bre.run("abi-encode-withselector", {
|
||||
abi: ConnectMaker.abi,
|
||||
functionname: "open",
|
||||
inputs: ["ETH-A"],
|
||||
});
|
||||
|
||||
await dsa.cast([bre.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(
|
||||
[bre.network.config.ConnectMaker],
|
||||
[
|
||||
await bre.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(
|
||||
[bre.network.config.ConnectMaker],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectMaker.abi,
|
||||
functionname: "borrow",
|
||||
inputs: [cdpId, ethers.utils.parseUnits("1000", 18), 0, 0],
|
||||
}),
|
||||
],
|
||||
userAddress
|
||||
);
|
||||
|
||||
expect(await daiToken.balanceOf(dsa.address)).to.be.equal(
|
||||
ethers.utils.parseEther("1000")
|
||||
);
|
||||
// Add ETH/USD Maker Medianizer in the Oracle Aggregator
|
||||
|
||||
await oracleAggregator.addOracle(
|
||||
"ETH/USD",
|
||||
"0x729D19f657BD0614b4985Cf1D82531c67569197B"
|
||||
);
|
||||
});
|
||||
|
||||
it("#1: ok should return NotOKMakerVaultIsSafe when the ETH/USD price is above the defined limit", async function () {
|
||||
let data = await conditionMakerVaultIsSafe.getConditionData(
|
||||
cdpId,
|
||||
"ETH/USD",
|
||||
ethers.utils.parseUnits("30", 17)
|
||||
);
|
||||
|
||||
expect(await conditionMakerVaultIsSafe.ok(0, data, 0)).to.be.equal(
|
||||
"NotOKMakerVaultIsSafe"
|
||||
);
|
||||
});
|
||||
|
||||
it("#2: ok should return OK when the ETH/USD price is lower than the defined limit", async function () {
|
||||
let data = await conditionMakerVaultIsSafe.getConditionData(
|
||||
cdpId,
|
||||
"ETH/USD",
|
||||
ethers.utils.parseUnits("30", 17)
|
||||
);
|
||||
|
||||
//#region Mock Part
|
||||
|
||||
oracleAggregator.mock(true, ethers.utils.parseUnits("299", 18));
|
||||
|
||||
//#endregion
|
||||
|
||||
expect(await conditionMakerVaultIsSafe.ok(0, data, 0)).to.be.equal(
|
||||
"NotOKMakerVaultIsSafe"
|
||||
);
|
||||
});
|
||||
});
|
281
test/4_ConnectGelatoProviderPayment.test.js
Normal file
281
test/4_ConnectGelatoProviderPayment.test.js
Normal file
|
@ -0,0 +1,281 @@
|
|||
const {expect} = require("chai");
|
||||
const bre = require("@nomiclabs/buidler");
|
||||
const {ethers} = bre;
|
||||
|
||||
// #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 ConnectBasic = require("../pre-compiles/ConnectBasic.json");
|
||||
const InstaList = require("../pre-compiles/InstaList.json");
|
||||
const InstaAccount = require("../pre-compiles/InstaAccount.json");
|
||||
const InstaIndex = require("../pre-compiles/InstaIndex.json");
|
||||
const IERC20 = require("../pre-compiles/IERC20.json");
|
||||
const InstaConnector = require("../pre-compiles/InstaConnectors.json");
|
||||
const ConnectGelatoProviderPaymentABI = require("../artifacts/ConnectGelatoProviderPayment.json");
|
||||
|
||||
// #endregion
|
||||
|
||||
describe("Gelato Provider Payment Connector unit test", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
console.error("Test Suite is meant to be run on ganache only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let userWallet;
|
||||
let userAddress;
|
||||
let providerWallet;
|
||||
let providerAddress;
|
||||
|
||||
let instaList;
|
||||
let instaIndex;
|
||||
let daiToken;
|
||||
let instaConnectors;
|
||||
let instaMaster;
|
||||
let connectBasic;
|
||||
let getCdps;
|
||||
let dssCdpManager;
|
||||
|
||||
let connectGelatoProviderPayment;
|
||||
|
||||
let dsa;
|
||||
let cdpId;
|
||||
|
||||
before(async function () {
|
||||
// Get Test Wallet for local testnet
|
||||
[userWallet] = await ethers.getSigners();
|
||||
userAddress = await userWallet.getAddress();
|
||||
|
||||
[, providerWallet] = await ethers.getSigners();
|
||||
providerAddress = await providerWallet.getAddress();
|
||||
|
||||
instaMaster = await ethers.provider.getSigner(
|
||||
bre.network.config.InstaMaster
|
||||
);
|
||||
|
||||
// Ganache default accounts prefilled with 100 ETH
|
||||
expect(await userWallet.getBalance()).to.be.gt(
|
||||
ethers.utils.parseEther("10")
|
||||
);
|
||||
|
||||
instaIndex = await ethers.getContractAt(
|
||||
InstaIndex.abi,
|
||||
bre.network.config.InstaIndex
|
||||
);
|
||||
instaList = await ethers.getContractAt(
|
||||
InstaList.abi,
|
||||
bre.network.config.InstaList
|
||||
);
|
||||
connectBasic = await ethers.getContractAt(
|
||||
ConnectBasic.abi,
|
||||
bre.network.config.ConnectBasic
|
||||
);
|
||||
instaConnectors = await ethers.getContractAt(
|
||||
InstaConnector.abi,
|
||||
bre.network.config.InstaConnectors
|
||||
);
|
||||
getCdps = await ethers.getContractAt(
|
||||
GetCdps.abi,
|
||||
bre.network.config.GetCdps
|
||||
);
|
||||
dssCdpManager = await ethers.getContractAt(
|
||||
DssCdpManager.abi,
|
||||
bre.network.config.DssCdpManager
|
||||
);
|
||||
daiToken = await ethers.getContractAt(IERC20.abi, bre.network.config.DAI);
|
||||
|
||||
// ========== Test Setup ============
|
||||
|
||||
const connectorLength = await instaConnectors.connectorLength();
|
||||
const connectorId = connectorLength.add(1);
|
||||
|
||||
const ConnectGelatoProviderPayment = await ethers.getContractFactory(
|
||||
"ConnectGelatoProviderPayment"
|
||||
);
|
||||
connectGelatoProviderPayment = await ConnectGelatoProviderPayment.deploy(
|
||||
connectorId
|
||||
);
|
||||
connectGelatoProviderPayment.deployed();
|
||||
|
||||
await instaConnectors
|
||||
.connect(instaMaster)
|
||||
.enable(connectGelatoProviderPayment.address);
|
||||
|
||||
await userWallet.sendTransaction({
|
||||
to: bre.network.config.InstaMaster,
|
||||
value: ethers.utils.parseEther("0.1"),
|
||||
});
|
||||
|
||||
expect(
|
||||
await instaConnectors.isConnector([connectGelatoProviderPayment.address])
|
||||
).to.be.true;
|
||||
|
||||
// ========== Create DeFi Smart Account for User 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)
|
||||
);
|
||||
});
|
||||
|
||||
it("#1: payProvider should pay to Provider 300x10^18 token dai", async function () {
|
||||
let providerDAIBalanceBefore = await daiToken.balanceOf(providerAddress);
|
||||
|
||||
await dsa.cast(
|
||||
[bre.network.config.ConnectMaker],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectMaker.abi,
|
||||
functionname: "open",
|
||||
inputs: ["ETH-A"],
|
||||
}),
|
||||
],
|
||||
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(
|
||||
[bre.network.config.ConnectMaker],
|
||||
[
|
||||
await bre.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(
|
||||
[bre.network.config.ConnectMaker],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectMaker.abi,
|
||||
functionname: "borrow",
|
||||
inputs: [cdpId, ethers.utils.parseUnits("1000", 18), 0, 0],
|
||||
}),
|
||||
],
|
||||
userAddress
|
||||
);
|
||||
|
||||
expect(await daiToken.balanceOf(dsa.address)).to.be.equal(
|
||||
ethers.utils.parseEther("1000")
|
||||
);
|
||||
|
||||
await dsa.cast(
|
||||
[connectGelatoProviderPayment.address],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectGelatoProviderPaymentABI.abi,
|
||||
functionname: "payProvider",
|
||||
inputs: [
|
||||
providerAddress,
|
||||
daiToken.address,
|
||||
ethers.utils.parseUnits("300", 18),
|
||||
0,
|
||||
0,
|
||||
],
|
||||
}),
|
||||
],
|
||||
userAddress
|
||||
);
|
||||
|
||||
expect(await daiToken.balanceOf(providerAddress)).to.be.equal(
|
||||
providerDAIBalanceBefore.add(ethers.utils.parseUnits("300", 18))
|
||||
);
|
||||
});
|
||||
|
||||
it("#2: payProvider should pay to Provider 1 ether", async function () {
|
||||
let providerBalanceBefore = await providerWallet.getBalance();
|
||||
|
||||
await dsa.cast(
|
||||
[connectBasic.address, connectGelatoProviderPayment.address],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectBasic.abi,
|
||||
functionname: "deposit",
|
||||
inputs: [
|
||||
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
ethers.utils.parseEther("1"),
|
||||
0,
|
||||
"105",
|
||||
],
|
||||
}),
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectGelatoProviderPaymentABI.abi,
|
||||
functionname: "payProvider",
|
||||
inputs: [
|
||||
providerAddress,
|
||||
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
0,
|
||||
"105",
|
||||
0,
|
||||
],
|
||||
}),
|
||||
],
|
||||
userAddress,
|
||||
{
|
||||
value: ethers.utils.parseEther("1"),
|
||||
}
|
||||
);
|
||||
|
||||
expect(await providerWallet.getBalance()).to.be.equal(
|
||||
providerBalanceBefore.add(ethers.utils.parseEther("1"))
|
||||
);
|
||||
});
|
||||
|
||||
it("#3: payProvider should return error message ConnectGelatoProviderPayment.payProvider:INVALIDADDESS when provider is Zero Address", async function () {
|
||||
expect(
|
||||
dsa.cast(
|
||||
[connectBasic.address, connectGelatoProviderPayment.address],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectBasic.abi,
|
||||
functionname: "deposit",
|
||||
inputs: [
|
||||
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
ethers.utils.parseEther("1"),
|
||||
0,
|
||||
"105",
|
||||
],
|
||||
}),
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectGelatoProviderPaymentABI.abi,
|
||||
functionname: "payProvider",
|
||||
inputs: [
|
||||
ethers.constants.AddressZero,
|
||||
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
0,
|
||||
"105",
|
||||
0,
|
||||
],
|
||||
}),
|
||||
],
|
||||
userAddress,
|
||||
{
|
||||
value: ethers.utils.parseEther("1"),
|
||||
}
|
||||
)
|
||||
).to.be.revertedWith(
|
||||
"ConnectGelatoProviderPayment.payProvider:INVALIDADDESS."
|
||||
);
|
||||
});
|
||||
});
|
51
test/5_OracleAggregator.test.js
Normal file
51
test/5_OracleAggregator.test.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
const {expect} = require("chai");
|
||||
const bre = require("@nomiclabs/buidler");
|
||||
const {ethers} = bre;
|
||||
|
||||
describe("Oracle Aggregator unit test", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
console.error("Test Suite is meant to be run on ganache only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let oracleAggregator;
|
||||
|
||||
before(async function () {
|
||||
const OracleAggregator = await ethers.getContractFactory(
|
||||
"OracleAggregator"
|
||||
);
|
||||
oracleAggregator = await OracleAggregator.deploy();
|
||||
oracleAggregator.deployed();
|
||||
});
|
||||
|
||||
it("#1: addOracle should add a maker medianizer for a currencyPair", async function () {
|
||||
await oracleAggregator.addOracle(
|
||||
"ETH/USD",
|
||||
"0x729D19f657BD0614b4985Cf1D82531c67569197B"
|
||||
);
|
||||
expect(await oracleAggregator.makerOracle("ETH/USD")).to.be.equal(
|
||||
"0x729D19f657BD0614b4985Cf1D82531c67569197B"
|
||||
);
|
||||
});
|
||||
|
||||
it("#2: addOracle should revert when adding a maker medianizer and for this currency pair it was been already added", async function () {
|
||||
expect(
|
||||
oracleAggregator.addOracle(
|
||||
"ETH/USD",
|
||||
"0x729D19f657BD0614b4985Cf1D82531c67569197B"
|
||||
)
|
||||
).to.be.revertedWith("OracleAggregator.Maker: Oracle already set.");
|
||||
});
|
||||
|
||||
it("#3: getMakerTokenPrice should return ETH/USD prize", async function () {
|
||||
expect((await oracleAggregator.getMakerTokenPrice("ETH/USD")).isZero()).to
|
||||
.be.false;
|
||||
});
|
||||
|
||||
it("#4: getMakerTokenPrice should return OracleAggregator.getMakerTokenPrice: CurrencyPairNotSupported. when currencyPair are not supported / not been added", async function () {
|
||||
expect(oracleAggregator.getMakerTokenPrice("ETH/DAI")).to.be.revertedWith(
|
||||
"OracleAggregator.getMakerTokenPrice: CurrencyPairNotSupported."
|
||||
);
|
||||
});
|
||||
});
|
195
test/6_ProviderModuleDSA.test.js
Normal file
195
test/6_ProviderModuleDSA.test.js
Normal file
|
@ -0,0 +1,195 @@
|
|||
const {expect} = require("chai");
|
||||
const bre = require("@nomiclabs/buidler");
|
||||
const {ethers} = bre;
|
||||
const GelatoCoreLib = require("@gelatonetwork/core");
|
||||
|
||||
// #region Contracts ABI
|
||||
|
||||
const ConnectAuth = require("../pre-compiles/ConnectAuth.json");
|
||||
const InstaList = require("../pre-compiles/InstaList.json");
|
||||
const InstaAccount = require("../pre-compiles/InstaAccount.json");
|
||||
const InstaIndex = require("../pre-compiles/InstaIndex.json");
|
||||
const InstaConnectors = require("../pre-compiles/InstaConnectors.json");
|
||||
const ConnectGelatoProviderPaymentABI = require("../artifacts/ConnectGelatoProviderPayment.json");
|
||||
|
||||
const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
|
||||
// #endregion
|
||||
|
||||
describe("Provider Module unit test", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
console.error("Test Suite is meant to be run on ganache only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let providerModuleDSA;
|
||||
let connectGelatoProviderPayment;
|
||||
|
||||
let instaIndex;
|
||||
let gelatoCore;
|
||||
let instaConnectors;
|
||||
let instaList;
|
||||
|
||||
let userWallet;
|
||||
let userAddress;
|
||||
let providerWallet;
|
||||
let providerAddress;
|
||||
let dsa;
|
||||
|
||||
before(async function () {
|
||||
// Get Test Wallet for local testnet
|
||||
[userWallet] = await ethers.getSigners();
|
||||
userAddress = await userWallet.getAddress();
|
||||
|
||||
[, providerWallet] = await ethers.getSigners();
|
||||
providerAddress = await providerWallet.getAddress();
|
||||
|
||||
// Ganache default accounts prefilled with 100 ETH
|
||||
expect(await userWallet.getBalance()).to.be.gt(
|
||||
ethers.utils.parseEther("10")
|
||||
);
|
||||
/////////////////// Get Deployed Contract //////////////////
|
||||
instaIndex = await ethers.getContractAt(
|
||||
InstaIndex.abi,
|
||||
bre.network.config.InstaIndex
|
||||
);
|
||||
instaConnectors = await ethers.getContractAt(
|
||||
InstaConnectors.abi,
|
||||
bre.network.config.InstaConnectors
|
||||
);
|
||||
gelatoCore = await ethers.getContractAt(
|
||||
GelatoCoreLib.GelatoCore.abi,
|
||||
bre.network.config.GelatoCore
|
||||
);
|
||||
instaList = await ethers.getContractAt(
|
||||
InstaList.abi,
|
||||
bre.network.config.InstaList
|
||||
);
|
||||
|
||||
////////////////// Deploy Needed Contracts ////////////////////////
|
||||
const connectorLength = await instaConnectors.connectorLength();
|
||||
const connectorId = connectorLength.add(1);
|
||||
|
||||
const ConnectGelatoProviderPayment = await ethers.getContractFactory(
|
||||
"ConnectGelatoProviderPayment"
|
||||
);
|
||||
connectGelatoProviderPayment = await ConnectGelatoProviderPayment.deploy(
|
||||
connectorId
|
||||
);
|
||||
await connectGelatoProviderPayment.deployed();
|
||||
|
||||
const ProviderModuleDSA = await ethers.getContractFactory(
|
||||
"ProviderModuleDSA"
|
||||
);
|
||||
providerModuleDSA = await ProviderModuleDSA.deploy(
|
||||
instaIndex.address,
|
||||
gelatoCore.address,
|
||||
connectGelatoProviderPayment.address
|
||||
);
|
||||
await providerModuleDSA.deployed();
|
||||
|
||||
///////////////// Setup /////////////////////////
|
||||
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)
|
||||
);
|
||||
});
|
||||
|
||||
// Uncomment when ethers bug will be solved. revertedWith produce the following during call "AssertionError: Expected transaction to be reverted"
|
||||
// it("isProvided should revert due to none listing of userProxy", async function () {
|
||||
// expect(
|
||||
// providerModuleDSA.isProvided(
|
||||
// ethers.constants.AddressZero,
|
||||
// ethers.constants.AddressZero,
|
||||
// [[], [], 0, 0]
|
||||
// )
|
||||
// ).to.be.revertedWith("ProviderModuleDSA.isProvided:InvalidUserProxy");
|
||||
// });
|
||||
|
||||
// it("isProvided should revert due to lack of right of gelatoCore to act on the dsa behalf", async function () {
|
||||
// expect(
|
||||
// providerModuleDSA.isProvided(
|
||||
// dsa.address,
|
||||
// ethers.constants.AddressZero,
|
||||
// [[], [], 0, 0]
|
||||
// )
|
||||
// ).to.be.revertedWith("ProviderModuleDSA.isProvided:GelatoCoreNotAuth");
|
||||
// });
|
||||
|
||||
it("#1: isProvided should return OK", async function () {
|
||||
// Give authorization to Gelato on user DSA
|
||||
await dsa.cast(
|
||||
[bre.network.config.ConnectAuth],
|
||||
[
|
||||
await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectAuth.abi,
|
||||
functionname: "add",
|
||||
inputs: [gelatoCore.address],
|
||||
}),
|
||||
],
|
||||
userAddress
|
||||
);
|
||||
|
||||
expect(await dsa.isAuth(gelatoCore.address)).to.be.true;
|
||||
|
||||
expect(
|
||||
await providerModuleDSA.isProvided(
|
||||
dsa.address,
|
||||
ethers.constants.AddressZero,
|
||||
[[], [], 0, 0]
|
||||
)
|
||||
).to.be.equal("OK");
|
||||
});
|
||||
|
||||
it("#2: execPayload should return payload with the right provider", async function () {
|
||||
// Task creation for sending to execPayload
|
||||
let payProvider = new GelatoCoreLib.Action({
|
||||
addr: connectGelatoProviderPayment.address,
|
||||
data: await bre.run("abi-encode-withselector", {
|
||||
abi: ConnectGelatoProviderPaymentABI.abi,
|
||||
functionname: "payProvider",
|
||||
inputs: [ethers.constants.AddressZero, ETH, 0, "105", 0],
|
||||
}),
|
||||
operation: GelatoCoreLib.Operation.Delegatecall,
|
||||
});
|
||||
|
||||
const task = new GelatoCoreLib.Task({
|
||||
conditions: [],
|
||||
actions: [payProvider],
|
||||
});
|
||||
|
||||
let result = await providerModuleDSA.execPayload(
|
||||
0,
|
||||
ethers.constants.AddressZero,
|
||||
providerAddress,
|
||||
task,
|
||||
0
|
||||
);
|
||||
|
||||
//#region retrieving the replaced provider address from the payload
|
||||
let abi = new ethers.utils.AbiCoder();
|
||||
|
||||
let datas = abi.decode(
|
||||
["address[]", "bytes[]", "address"],
|
||||
ethers.utils.hexDataSlice(result.payload, 4)
|
||||
)[1];
|
||||
|
||||
let paymentReceivingAddress = abi.decode(
|
||||
["address", "address", "uint256", "uint256", "uint256"],
|
||||
ethers.utils.hexDataSlice(datas[0], 4)
|
||||
)[0];
|
||||
//#endregion
|
||||
expect(paymentReceivingAddress).to.be.equal(providerAddress);
|
||||
});
|
||||
});
|
141
test/7_ConnectGelatoDebtBridge.test.js
Normal file
141
test/7_ConnectGelatoDebtBridge.test.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
const {expect} = require("chai");
|
||||
const bre = require("@nomiclabs/buidler");
|
||||
const {ethers} = bre;
|
||||
|
||||
const WAD = ethers.utils.parseUnits("1", 18);
|
||||
|
||||
//#region DSMath function
|
||||
|
||||
let wdiv = (x, y) => {
|
||||
return x.mul(WAD).add(y.div(2)).div(y);
|
||||
};
|
||||
|
||||
let wmul = (x, y) => {
|
||||
return x.mul(y).add(WAD.div(2)).div(WAD);
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
describe("Gelato Debt Bridge Connector unit test", function () {
|
||||
this.timeout(0);
|
||||
if (bre.network.name !== "ganache") {
|
||||
console.error("Test Suite is meant to be run on ganache only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let connectGelatoDebtBridge;
|
||||
before(async function () {
|
||||
const ConnectGelatoDebtBridge = await ethers.getContractFactory(
|
||||
"ConnectGelatoDebtBridgeMock"
|
||||
);
|
||||
connectGelatoDebtBridge = await ConnectGelatoDebtBridge.deploy(
|
||||
0,
|
||||
ethers.constants.AddressZero
|
||||
);
|
||||
connectGelatoDebtBridge.deployed();
|
||||
});
|
||||
|
||||
it("#1: _wcollateralToWithdraw should return the amount of collateral to withdraw on protocol 1 and to put on protocol 2", async function () {
|
||||
// 3 times more collateral than borrowed amount in protocol 1
|
||||
let wantedLiquidationRatioOnProtocol1 = ethers.utils.parseUnits("3", 18);
|
||||
// 1.5 times more collateral than borrowed amount in protocol 2
|
||||
let wantedLiquidationRatioOnProtocol2 = ethers.utils.parseUnits("15", 17);
|
||||
// The amount of collateral locked
|
||||
let col = ethers.utils.parseUnits("1", 18);
|
||||
// The amount of borrowed token
|
||||
let borrowedToken = ethers.utils.parseUnits("100", 18);
|
||||
// how much one collateral is worth on borrowed token
|
||||
let collateralPrice = ethers.utils.parseUnits("250", 18);
|
||||
// the amount of collateral in borrowed token
|
||||
let collateral = col
|
||||
.mul(collateralPrice)
|
||||
.div(ethers.utils.parseUnits("1", 18)); // div to have everything in wad standard
|
||||
|
||||
// Check this document https://drive.google.com/file/d/1OV3ZbJPd2Yr-3l0rst6tK3ycfhhg6Nfh/view?usp=sharing for more details one the used formula
|
||||
|
||||
//#region CALCULATION REPLICATION
|
||||
|
||||
let expectedColToWithdraw = wmul(
|
||||
wmul(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2
|
||||
),
|
||||
borrowedToken
|
||||
); // doc ref : c_r x comp_r x d_2
|
||||
expectedColToWithdraw = expectedColToWithdraw.sub(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, collateral)
|
||||
); // doc ref : c_r x comp_r x d_2 - c_r x e_2
|
||||
expectedColToWithdraw = wdiv(
|
||||
expectedColToWithdraw,
|
||||
wantedLiquidationRatioOnProtocol2.sub(wantedLiquidationRatioOnProtocol1)
|
||||
); // doc ref : (c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r)
|
||||
expectedColToWithdraw = collateral.sub(expectedColToWithdraw); // doc ref : e_2 - ((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
|
||||
// Extra step to convert back to col type
|
||||
expectedColToWithdraw = wdiv(expectedColToWithdraw, collateralPrice);
|
||||
|
||||
//#endregion
|
||||
|
||||
expect(
|
||||
await connectGelatoDebtBridge.wcollateralToWithdraw(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
borrowedToken,
|
||||
collateralPrice
|
||||
)
|
||||
).to.be.equal(expectedColToWithdraw);
|
||||
});
|
||||
|
||||
it("#2: _wborrowedTokenToPayback should return the amount of borrowed token to pay back on protocol 1", async function () {
|
||||
// 3 times more collateral than borrowed amount in protocol 1
|
||||
let wantedLiquidationRatioOnProtocol1 = ethers.utils.parseUnits("3", 18);
|
||||
// 1.5 times more collateral than borrowed amount in protocol 2
|
||||
let wantedLiquidationRatioOnProtocol2 = ethers.utils.parseUnits("15", 17);
|
||||
// The amount of collateral locked
|
||||
let col = ethers.utils.parseUnits("1", 18);
|
||||
// The amount of borrowed token
|
||||
let borrowedToken = ethers.utils.parseUnits("100", 18);
|
||||
// how much one collateral is worth on borrowed token
|
||||
let collateralPrice = ethers.utils.parseUnits("250", 18);
|
||||
// the amount of collateral in borrowed token
|
||||
let collateral = col
|
||||
.mul(collateralPrice)
|
||||
.div(ethers.utils.parseUnits("1", 18)); // div to have everything in wad standard
|
||||
|
||||
// Check this document https://drive.google.com/file/d/1OV3ZbJPd2Yr-3l0rst6tK3ycfhhg6Nfh/view?usp=sharing for more details one the used formula
|
||||
|
||||
//#region CALCULATION REPLICATION
|
||||
|
||||
let expectedBorToPayBack = wmul(
|
||||
wmul(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2
|
||||
),
|
||||
borrowedToken
|
||||
); // doc ref : c_r x comp_r x d_2
|
||||
expectedBorToPayBack = expectedBorToPayBack.sub(
|
||||
wmul(wantedLiquidationRatioOnProtocol1, collateral)
|
||||
); // doc ref : c_r x comp_r x d_2 - c_r x e_2
|
||||
expectedBorToPayBack = wdiv(
|
||||
expectedBorToPayBack,
|
||||
wantedLiquidationRatioOnProtocol2.sub(wantedLiquidationRatioOnProtocol1)
|
||||
); // doc ref : (c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r)
|
||||
expectedBorToPayBack = wmul(
|
||||
wdiv(ethers.utils.parseUnits("1", 18), wantedLiquidationRatioOnProtocol1),
|
||||
expectedBorToPayBack
|
||||
); // doc ref : (1/c_r)((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
expectedBorToPayBack = borrowedToken.sub(expectedBorToPayBack); // doc ref : d_2 - (1/c_r)((c_r x comp_r x d_2 - c_r x e_2)/ (comp_r - c_r))
|
||||
|
||||
//#endregion
|
||||
|
||||
expect(
|
||||
await connectGelatoDebtBridge.wborrowedTokenToPayback(
|
||||
wantedLiquidationRatioOnProtocol1,
|
||||
wantedLiquidationRatioOnProtocol2,
|
||||
collateral,
|
||||
borrowedToken
|
||||
)
|
||||
).to.be.equal(expectedBorToPayBack);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user