feat: new ConnectGelato and ProviderModuleDSA

This commit is contained in:
gitpusha 2020-12-01 13:41:52 +01:00 committed by Twin Fish
parent a001839207
commit bddba4f3d8
29 changed files with 1339 additions and 2903 deletions

View File

@ -37,13 +37,13 @@ jobs: # a collection of steps
command: yarn lint
- restore_cache: # restore the Hardhat Network Fork Cache
name: Restore Hardhat Network Fork Cache
key: v5-hardhat-network-fork-cache
key: v6-hardhat-network-fork-cache
- run: # Tests
name: Tests using hardhat mainnet fork and gas reporter
command: yarn test:gas
- save_cache: # special step to save the Hardhat Network Fork cache
name: Save Hardhat Network Fork Cache
key: v5-hardhat-network-fork-cache
key: v6-hardhat-network-fork-cache
paths:
- ./cache/hardhat-network-fork
- run: # Codechecks

View File

@ -22,7 +22,7 @@ Furtheremore the following contracts were added to showcase the automation of th
- `ConditionCompareUintsFromTwoSource`: a generic Gelato Condition that allows you to read and compare data from 2 arbitrary on-chain sources (returndata expected to be uint256 and normalized => hence MockDSR and MockCDAI). This Condition was used to compare DSR to CDAI rates and in the test suite we showcase how a change in the CDAI rate (it going above the DSR) can trigger an automatic rebalancing from DSR to CDAI via DSA Connectors.
- `ProviderModuleDsa`: this is needed for any Gelato integration. It tells Gelato how the execution payload should be formatted. In this prototype, it formats the payload for the `DSA.cast` function.
- `ProviderModuleDSA`: this is needed for any Gelato integration. It tells Gelato how the execution payload should be formatted. In this prototype, it formats the payload for the `DSA.cast` function.
- `ConnectGelato`: this is a Connector needed for the DSA to be able to submit Tasks to Gelato. In the test suite we unlock the DSA MultiSig Master account at 0xfCD22438AD6eD564a1C26151Df73F6B33B817B56, in order to be able to enable this Connector in our mainnet fork running on the local hardhat network instance.

View File

@ -1,7 +1,7 @@
const INSTA_MASTER = "0xb1DC62EC38E6E3857a887210C38418E4A17Da5B2";
module.exports = {
GelatoCore: "0x1d681d76ce96E4d70a88A00EBbcfc1E47808d0b8",
GelatoCore: "0x025030BdAa159f281cAe63873E68313a703725A5",
GelatoGasPriceOracle: "0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C",
InstaMaster: INSTA_MASTER,
InstaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
@ -11,7 +11,6 @@ module.exports = {
InstaMapping: "0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88",
ConnectAuth: "0xd1aFf9f2aCf800C876c409100D6F39AEa93Fc3D9",
ConnectBasic: "0x6a31c5982C5Bc5533432913cf06a66b6D3333a95",
ConnectGelato: "0x37A7009d424951dd5D5F155fA588D9a03C455163",
ConnectMaker: "0xac02030d8a8F49eD04b2f52C394D3F901A10F8A9",
ConnectCompound: "0x15FdD1e902cAC70786fe7D31013B1a806764B5a2",
ConnectInstaPool: "0xeB4bf86589f808f90EEC8e964dBF16Bd4D284905",
@ -24,5 +23,4 @@ module.exports = {
CETH: "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5",
DssCdpManager: "0x5ef30b9986345249bc32d8928B7ee64DE9435E39",
GetCdps: "0x36a724Bd100c39f0Ea4D3A20F7097eE01A8Ff573",
ProviderModuleDsa: "0x0C25452d20cdFeEd2983fa9b9b9Cf4E81D6f2fE2",
};

View File

@ -1,9 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
import "@gelatonetwork/core/contracts/gelato_core/GelatoCore.sol";
// solhint-disable-next-line no-empty-blocks
contract DGelatoCore {
}

View File

@ -0,0 +1,404 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
// solhint-disable
// Gelato Data Types
struct Provider {
address addr; // if msg.sender == provider => self-Provider
address module; // e.g. DSA Provider Module
}
struct Condition {
address inst; // can be AddressZero for self-conditional Actions
bytes data; // can be bytes32(0) for self-conditional Actions
}
enum Operation {Call, Delegatecall}
enum DataFlow {None, In, Out, InAndOut}
struct Action {
address addr;
bytes data;
Operation operation;
DataFlow dataFlow;
uint256 value;
bool termsOkCheck;
}
struct Task {
Condition[] conditions; // optional
Action[] actions;
uint256 selfProviderGasLimit; // optional: 0 defaults to gelatoMaxGas
uint256 selfProviderGasPriceCeil; // optional: 0 defaults to NO_CEIL
}
struct TaskReceipt {
uint256 id;
address userProxy;
Provider provider;
uint256 index;
Task[] tasks;
uint256 expiryDate;
uint256 cycleId; // auto-filled by GelatoCore. 0 for non-cyclic/chained tasks
uint256 submissionsLeft;
}
struct TaskSpec {
address[] conditions; // Address: optional AddressZero for self-conditional actions
Action[] actions;
uint256 gasPriceCeil;
}
// Gelato Interface
interface IGelatoInterface {
/**
* @dev API to submit a single Task.
*/
function submitTask(
Provider calldata _provider,
Task calldata _task,
uint256 _expiryDate
) external;
/**
* @dev A Gelato Task Cycle consists of 1 or more Tasks that automatically submit
* the next one, after they have been executed, where the total number of tasks can
* be only be an even number
*/
function submitTaskCycle(
Provider calldata _provider,
Task[] calldata _tasks,
uint256 _expiryDate,
uint256 _cycles
) external;
/**
* @dev A Gelato Task Chain consists of 1 or more Tasks that automatically submit
* the next one, after they have been executed, where the total number of tasks can
* be an odd number
*/
function submitTaskChain(
Provider calldata _provider,
Task[] calldata _tasks,
uint256 _expiryDate,
uint256 _sumOfRequestedTaskSubmits
) external;
/**
* @dev Cancel multiple tasks at once
*/
function multiCancelTasks(TaskReceipt[] calldata _taskReceipts) external;
/**
* @dev Whitelist new executor, TaskSpec(s) and Module(s) in one tx
*/
function multiProvide(
address _executor,
TaskSpec[] calldata _taskSpecs,
address[] calldata _modules
) external payable;
/**
* @dev De-Whitelist TaskSpec(s), Module(s) and withdraw funds from gelato in one tx
*/
function multiUnprovide(
uint256 _withdrawAmount,
TaskSpec[] calldata _taskSpecs,
address[] calldata _modules
) external;
}
interface MemoryInterface {
function setUint(uint256 _id, uint256 _val) external;
function getUint(uint256 _id) external returns (uint256);
}
abstract contract Helpers {
uint256 internal immutable _id;
constructor(uint256 id) {
_id = id;
}
/**
* @dev Return Memory Variable Address
*/
function getMemoryAddr() internal pure returns (address) {
return 0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F; // InstaMemory Address
}
/**
* @dev Set Uint value in InstaMemory Contract.
*/
function setUint(uint256 setId, uint256 val) internal {
if (setId != 0) MemoryInterface(getMemoryAddr()).setUint(setId, val);
}
/**
* @dev Get Uint value from InstaMemory Contract.
*/
function getUint(uint256 getId, uint256 val)
internal
returns (uint256 returnVal)
{
returnVal = getId == 0
? val
: MemoryInterface(getMemoryAddr()).getUint(getId);
}
/**
* @dev Connector Details
*/
function connectorID() public view returns (uint256 _type, uint256 id) {
(_type, id) = (1, _id);
}
}
contract DSMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "math-not-safe");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "sub-overflow");
}
}
abstract contract GelatoHelpers is Helpers, DSMath {
/**
* @dev Return Gelato Core Address
*/
function getGelatoCoreAddr() internal pure returns (address) {
return 0x025030BdAa159f281cAe63873E68313a703725A5; // Gelato Core address
}
/**
* @dev Return Instapp DSA Provider Module Address
*/
function getInstadappProviderModuleAddr() internal pure returns (address) {
return 0x0C25452d20cdFeEd2983fa9b9b9Cf4E81D6f2fE2; // ProviderModuleDSA Address
}
}
abstract contract GelatoResolver is GelatoHelpers {
event LogMultiProvide(
address indexed executor,
TaskSpec[] indexed taskspecs,
address[] indexed modules,
uint256 ethToDeposit,
uint256 getId,
uint256 setId
);
event LogSubmitTask(
Provider indexed provider,
Task indexed task,
uint256 indexed expiryDate,
uint256 getId,
uint256 setId
);
event LogSubmitTaskCycle(
Provider indexed provider,
Task[] indexed tasks,
uint256 indexed expiryDate,
uint256 getId,
uint256 setId
);
event LogSubmitTaskChain(
Provider indexed provider,
Task[] indexed tasks,
uint256 indexed expiryDate,
uint256 getId,
uint256 setId
);
event LogMultiUnprovide(
TaskSpec[] indexed taskspecs,
address[] indexed modules,
uint256 ethToWithdraw,
uint256 getId,
uint256 setId
);
event LogMultiCancelTasks(
TaskReceipt[] indexed taskReceipt,
uint256 getId,
uint256 setId
);
// ===== Gelato ENTRY APIs ======
/**
* @dev Enables first time users to pre-fund eth, whitelist an executor & register the
* ProviderModuleDSA.sol to be able to use Gelato
* @param _executor address of single execot node or gelato'S decentralized execution market
* @param _taskSpecs enables external providers to whitelist TaskSpecs on gelato
* @param _modules address of ProviderModuleDSA
* @param _ethToDeposit amount of eth to deposit on Gelato, only for self-providers
*/
function multiProvide(
address _executor,
TaskSpec[] calldata _taskSpecs,
address[] calldata _modules,
uint256 _ethToDeposit,
uint256 _getId,
uint256 _setId
) external payable {
uint256 ethToDeposit = getUint(_getId, _ethToDeposit);
ethToDeposit = ethToDeposit == uint256(-1)
? address(this).balance
: ethToDeposit;
IGelatoInterface(getGelatoCoreAddr()).multiProvide{value: ethToDeposit}(
_executor,
_taskSpecs,
_modules
);
setUint(_setId, ethToDeposit);
emit LogMultiProvide(
_executor,
_taskSpecs,
_modules,
ethToDeposit,
_getId,
_setId
);
}
/**
* @dev Submits a single, one-time task to Gelato
* @param _provider Consists of proxy module address (DSA) and provider address ()
* who will pay for the transaction execution
* @param _task Task specifying the condition and the action connectors
* @param _expiryDate Default 0, othweise timestamp after which the task expires
*/
function submitTask(
Provider calldata _provider,
Task calldata _task,
uint256 _expiryDate
) external payable {
IGelatoInterface(getGelatoCoreAddr()).submitTask(
_provider,
_task,
_expiryDate
);
emit LogSubmitTask(_provider, _task, _expiryDate, 0, 0);
}
/**
* @dev Submits single or mulitple Task Sequences to Gelato
* @param _provider Consists of proxy module address (DSA) and provider address ()
* who will pay for the transaction execution
* @param _tasks A sequence of Tasks, can be a single or multiples
* @param _expiryDate Default 0, othweise timestamp after which the task expires
* @param _cycles How often the Task List should be executed, e.g. 5 times
*/
function submitTaskCycle(
Provider calldata _provider,
Task[] calldata _tasks,
uint256 _expiryDate,
uint256 _cycles
) external payable {
IGelatoInterface(getGelatoCoreAddr()).submitTaskCycle(
_provider,
_tasks,
_expiryDate,
_cycles
);
emit LogSubmitTaskCycle(_provider, _tasks, _expiryDate, 0, 0);
}
/**
* @dev Submits single or mulitple Task Chains to Gelato
* @param _provider Consists of proxy module address (DSA) and provider address ()
* who will pay for the transaction execution
* @param _tasks A sequence of Tasks, can be a single or multiples
* @param _expiryDate Default 0, othweise timestamp after which the task expires
* @param _sumOfRequestedTaskSubmits The TOTAL number of Task auto-submits
* that should have occured once the cycle is complete
*/
function submitTaskChain(
Provider calldata _provider,
Task[] calldata _tasks,
uint256 _expiryDate,
uint256 _sumOfRequestedTaskSubmits
) external payable {
IGelatoInterface(getGelatoCoreAddr()).submitTaskChain(
_provider,
_tasks,
_expiryDate,
_sumOfRequestedTaskSubmits
);
emit LogSubmitTaskChain(_provider, _tasks, _expiryDate, 0, 0);
}
// ===== Gelato EXIT APIs ======
/**
* @dev Withdraws funds from Gelato, de-whitelists TaskSpecs and Provider Modules
* in one tx
* @param _withdrawAmount Amount of ETH to withdraw from Gelato
* @param _taskSpecs List of Task Specs to de-whitelist, default empty []
* @param _modules List of Provider Modules to de-whitelist, default empty []
*/
function multiUnprovide(
uint256 _withdrawAmount,
TaskSpec[] calldata _taskSpecs,
address[] calldata _modules,
uint256 _getId,
uint256 _setId
) external payable {
uint256 withdrawAmount = getUint(_getId, _withdrawAmount);
uint256 balanceBefore = address(this).balance;
IGelatoInterface(getGelatoCoreAddr()).multiUnprovide(
withdrawAmount,
_taskSpecs,
_modules
);
uint256 actualWithdrawAmount =
sub(address(this).balance, balanceBefore);
setUint(_setId, actualWithdrawAmount);
emit LogMultiUnprovide(
_taskSpecs,
_modules,
actualWithdrawAmount,
_getId,
_setId
);
}
/**
* @dev Cancels outstanding Tasks
* @param _taskReceipts List of Task Receipts to cancel
*/
function multiCancelTasks(TaskReceipt[] calldata _taskReceipts)
external
payable
{
IGelatoInterface(getGelatoCoreAddr()).multiCancelTasks(_taskReceipts);
emit LogMultiCancelTasks(_taskReceipts, 0, 0);
}
}
contract ConnectGelato is GelatoResolver {
string public name = "ConnectGelato-v2.0";
constructor(uint256 _id) Helpers(_id) {}
}

View File

@ -0,0 +1,209 @@
// "SPDX-License-Identifier: UNLICENSED"
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
// solhint-disable
enum Operation {Call, Delegatecall}
enum DataFlow {None, In, Out, InAndOut}
interface IGelatoCondition {
/// @notice GelatoCore calls this to verify securely the specified Condition securely
/// @dev Be careful only to encode a Task's condition.data as is and not with the
/// "ok" selector or _taskReceiptId, since those two things are handled by GelatoCore.
/// @param _taskReceiptId This is passed by GelatoCore so we can rely on it as a secure
/// source of Task identification.
/// @param _conditionData This is the Condition.data field developers must encode their
/// Condition's specific parameters in.
/// @param _cycleId For Tasks that are executed as part of a cycle.
function ok(
uint256 _taskReceiptId,
bytes calldata _conditionData,
uint256 _cycleId
) external view returns (string memory);
}
struct Condition {
IGelatoCondition inst; // can be AddressZero for self-conditional Actions
bytes data; // can be bytes32(0) for self-conditional Actions
}
struct Action {
address addr;
bytes data;
Operation operation;
DataFlow dataFlow;
uint256 value;
bool termsOkCheck;
}
struct Task {
Condition[] conditions; // optional
Action[] actions;
uint256 selfProviderGasLimit; // optional: 0 defaults to gelatoMaxGas
uint256 selfProviderGasPriceCeil; // optional: 0 defaults to NO_CEIL
}
interface IGelatoProviderModule {
/// @notice Check if provider agrees to pay for inputted task receipt
/// @dev Enables arbitrary checks by provider
/// @param _userProxy The smart contract account of the user who submitted the Task.
/// @param _provider The account of the Provider who uses the ProviderModule.
/// @param _task Gelato Task to be executed.
/// @return "OK" if provider agrees
function isProvided(
address _userProxy,
address _provider,
Task calldata _task
) external view returns (string memory);
/// @notice Convert action specific payload into proxy specific payload
/// @dev Encoded multiple actions into a multisend
/// @param _taskReceiptId Unique ID of Gelato Task to be executed.
/// @param _userProxy The smart contract account of the user who submitted the Task.
/// @param _provider The account of the Provider who uses the ProviderModule.
/// @param _task Gelato Task to be executed.
/// @param _cycleId For Tasks that form part of a cycle/chain.
/// @return Encoded payload that will be used for low-level .call on user proxy
/// @return checkReturndata if true, fwd returndata from userProxy.call to ProviderModule
function execPayload(
uint256 _taskReceiptId,
address _userProxy,
address _provider,
Task calldata _task,
uint256 _cycleId
) external view returns (bytes memory, bool checkReturndata);
/// @notice Called by GelatoCore.exec to verifiy that no revert happend on userProxy
/// @dev If a caught revert is detected, this fn should revert with the detected error
/// @param _proxyReturndata Data from GelatoCore._exec.userProxy.call(execPayload)
function execRevertCheck(bytes calldata _proxyReturndata) external pure;
}
abstract contract GelatoProviderModuleStandard is IGelatoProviderModule {
string internal constant OK = "OK";
function isProvided(
address,
address,
Task calldata
) external view virtual override returns (string memory) {
return OK;
}
/// @dev Overriding fns should revert with the revertMsg they detected on the userProxy
function execRevertCheck(bytes calldata) external pure virtual override {
// By default no reverts detected => do nothing
}
}
/// @dev InstaDapp Index
interface IndexInterface {
function connectors(uint256 version) external view returns (address);
function list() external view returns (address);
}
/// @dev InstaDapp List
interface ListInterface {
function accountID(address _account) external view returns (uint64);
}
/// @dev InstaDapp Connectors
interface ConnectorsInterface {
function isConnector(address[] calldata logicAddr)
external
view
returns (bool);
function isStaticConnector(address[] calldata logicAddr)
external
view
returns (bool);
}
/// @dev InstaDapp Defi Smart Account wallet
interface AccountInterface {
function version() external view returns (uint256);
function isAuth(address user) external view returns (bool);
function shield() external view returns (bool);
function cast(
address[] calldata _targets,
bytes[] calldata _datas,
address _origin
) external payable returns (bytes32[] memory responses);
}
contract ProviderModuleDSA is GelatoProviderModuleStandard {
IndexInterface public immutable index;
address public immutable gelatoCore;
constructor(IndexInterface _index, address _gelatoCore) {
index = _index;
gelatoCore = _gelatoCore;
}
// ================= GELATO PROVIDER MODULE STANDARD ================
function isProvided(
address _userProxy,
address,
Task calldata
) external view override returns (string memory) {
// Verify InstaDapp account identity
if (ListInterface(index.list()).accountID(_userProxy) == 0)
return "ProviderModuleDSA.isProvided:InvalidUserProxy";
// Is GelatoCore authorized
if (!AccountInterface(_userProxy).isAuth(gelatoCore))
return "ProviderModuleDSA.isProvided:GelatoCoreNotAuth";
// @dev commented out for gas savings
// // Is connector valid
// ConnectorsInterface connectors = ConnectorsInterface(index.connectors(
// AccountInterface(_userProxy).version()
// ));
// address[] memory targets = new address[](_task.actions.length);
// for (uint i = 0; i < _task.actions.length; i++)
// targets[i] = _task.actions[i].addr;
// bool isShield = AccountInterface(_userProxy).shield();
// if (isShield)
// if (!connectors.isStaticConnector(targets))
// return "ProviderModuleDSA.isProvided:not-static-connector";
// else
// if (!connectors.isConnector(targets))
// return "ProviderModuleDSA.isProvided:not-connector";
return OK;
}
/// @dev DS PROXY ONLY ALLOWS DELEGATE CALL for single actions, that's why we also use multisend
function execPayload(
uint256,
address,
address,
Task calldata _task,
uint256
) external view override returns (bytes memory payload, bool) {
address[] memory targets = new address[](_task.actions.length);
for (uint256 i = 0; i < _task.actions.length; i++)
targets[i] = _task.actions[i].addr;
bytes[] memory datas = new bytes[](_task.actions.length);
for (uint256 i = 0; i < _task.actions.length; i++)
datas[i] = _task.actions[i].data;
payload = abi.encodeWithSelector(
AccountInterface.cast.selector,
targets,
datas,
gelatoCore
);
}
}

View File

@ -1,7 +1,4 @@
const { sleep } = require("@gelatonetwork/core");
const hre = require("hardhat");
const { ethers } = hre;
const GelatoCoreLib = require("@gelatonetwork/core");
module.exports = async (hre) => {
if (hre.network.name === "mainnet") {
@ -14,17 +11,12 @@ module.exports = async (hre) => {
const { deployments } = hre;
const { deploy } = deployments;
const { deployer } = await hre.getNamedAccounts();
const gelatoCore = await ethers.getContractAt(
GelatoCoreLib.GelatoCore.abi,
hre.network.config.GelatoCore
);
// the following will only deploy "MockDebtBridgeETHBExecutor"
// if the contract was never deployed or if the code changed since last deployment
await deploy("MockDebtBridgeETHBExecutor", {
from: deployer,
args: [gelatoCore.address],
value: await gelatoCore.minExecutorStake(),
args: [hre.network.config.GelatoCore],
gasPrice: hre.network.config.gasPrice,
log: hre.network.name === "mainnet" ? true : false,
});

View File

@ -0,0 +1,75 @@
const hre = require("hardhat");
const { ethers } = hre;
const { sleep } = require("@gelatonetwork/core");
const assert = require("assert");
module.exports = async (hre) => {
if (hre.network.name === "mainnet") {
console.log(
"\n\n Deploying ConnectGelato to mainnet. Hit ctrl + c to abort"
);
console.log("❗ CONNECTOR DEPLOYMENT: VERIFY & HARDCODE CONNECTOR ID");
console.log(`Connector Id: ${parseInt(process.env.CONNECTOR_ID)}`);
await sleep(10000);
}
const { deployments } = hre;
const { deploy } = deployments;
const { deployer } = await hre.getNamedAccounts();
if (hre.network.name === "hardhat") {
const deployerWallet = await ethers.provider.getSigner(deployer);
const instaMaster = await ethers.provider.getSigner(
hre.network.config.InstaMaster
);
await deployerWallet.sendTransaction({
to: await instaMaster.getAddress(),
value: ethers.utils.parseEther("0.1"),
});
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [await instaMaster.getAddress()],
});
const instaConnectors = await hre.ethers.getContractAt(
"InstaConnectors",
hre.network.config.InstaConnectors
);
const connectorLength = await instaConnectors.connectorLength();
const connectorId = connectorLength.add(1);
await deploy("ConnectGelato", {
from: deployer,
args: [connectorId],
});
await instaConnectors
.connect(instaMaster)
.enable((await ethers.getContract("ConnectGelato")).address);
await hre.network.provider.request({
method: "hardhat_stopImpersonatingAccount",
params: [await instaMaster.getAddress()],
});
} else {
assert(process.env.CONNECTOR_ID);
// the following will only deploy "ConnectGelato"
// if the contract was never deployed or if the code changed since last deployment
await deploy("ConnectGelato", {
from: deployer,
args: [parseInt(process.env.CONNECTOR_ID)],
gasPrice: hre.network.config.gasPrice,
log: true,
});
}
};
module.exports.skip = async (hre) => {
if (hre.network.name === "mainnet") return true;
if (hre.network.name !== "hardhat")
return process.env.CONNECTOR_ID === undefined;
return false;
};
module.exports.tags = ["ConnectGelato"];

View File

@ -0,0 +1,28 @@
const { sleep } = require("@gelatonetwork/core");
module.exports = async (hre) => {
if (hre.network.name === "mainnet") {
console.log(
"\n\n Deploying ProviderModuleDSA 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 "ConditionMakerVaultUnsafe"
// if the contract was never deployed or if the code changed since last deployment
await deploy("ProviderModuleDSA", {
from: deployer,
args: [hre.network.config.InstaIndex, hre.network.config.GelatoCore],
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 = ["ProviderModuleDSA"];

View File

@ -51,7 +51,7 @@ module.exports = {
// timeout: 150000,
forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
blockNumber: 11346751,
blockNumber: 11366500,
},
// Accounts
accounts: {

File diff suppressed because one or more lines are too long

View File

@ -1,934 +0,0 @@
[
{
"anonymous": false,
"inputs": [
{
"components": [
{ "internalType": "uint256", "name": "id", "type": "uint256" },
{ "internalType": "address", "name": "userProxy", "type": "address" },
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"internalType": "struct Provider",
"name": "provider",
"type": "tuple"
},
{ "internalType": "uint256", "name": "index", "type": "uint256" },
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "inst",
"type": "address"
},
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "address",
"name": "addr",
"type": "address"
},
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "bool",
"name": "termsOkCheck",
"type": "bool"
}
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct Task[]",
"name": "tasks",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "expiryDate",
"type": "uint256"
},
{ "internalType": "uint256", "name": "cycleId", "type": "uint256" },
{
"internalType": "uint256",
"name": "submissionsLeft",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct TaskReceipt[]",
"name": "taskReceipt",
"type": "tuple[]"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogMultiCancelTasks",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "executor",
"type": "address"
},
{
"components": [
{
"internalType": "address[]",
"name": "conditions",
"type": "address[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "gasPriceCeil",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct TaskSpec[]",
"name": "taskspecs",
"type": "tuple[]"
},
{
"indexed": true,
"internalType": "address[]",
"name": "modules",
"type": "address[]"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethToDeposit",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogMultiProvide",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{
"internalType": "address[]",
"name": "conditions",
"type": "address[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "gasPriceCeil",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct TaskSpec[]",
"name": "taskspecs",
"type": "tuple[]"
},
{
"indexed": true,
"internalType": "address[]",
"name": "modules",
"type": "address[]"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethToWithdraw",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogMultiUnprovide",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"indexed": true,
"internalType": "struct Provider",
"name": "provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct Task",
"name": "task",
"type": "tuple"
},
{
"indexed": true,
"internalType": "uint256",
"name": "expiryDate",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogSubmitTask",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"indexed": true,
"internalType": "struct Provider",
"name": "provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct Task[]",
"name": "tasks",
"type": "tuple[]"
},
{
"indexed": true,
"internalType": "uint256",
"name": "expiryDate",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogSubmitTaskChain",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"indexed": true,
"internalType": "struct Provider",
"name": "provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"indexed": true,
"internalType": "struct Task[]",
"name": "tasks",
"type": "tuple[]"
},
{
"indexed": true,
"internalType": "uint256",
"name": "expiryDate",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "getId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "setId",
"type": "uint256"
}
],
"name": "LogSubmitTaskCycle",
"type": "event"
},
{
"inputs": [],
"name": "connectorID",
"outputs": [
{ "internalType": "uint256", "name": "_type", "type": "uint256" },
{ "internalType": "uint256", "name": "_id", "type": "uint256" }
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"components": [
{ "internalType": "uint256", "name": "id", "type": "uint256" },
{ "internalType": "address", "name": "userProxy", "type": "address" },
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"internalType": "struct Provider",
"name": "provider",
"type": "tuple"
},
{ "internalType": "uint256", "name": "index", "type": "uint256" },
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "inst",
"type": "address"
},
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "address",
"name": "addr",
"type": "address"
},
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "bool",
"name": "termsOkCheck",
"type": "bool"
}
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct Task[]",
"name": "tasks",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "expiryDate",
"type": "uint256"
},
{ "internalType": "uint256", "name": "cycleId", "type": "uint256" },
{
"internalType": "uint256",
"name": "submissionsLeft",
"type": "uint256"
}
],
"internalType": "struct TaskReceipt[]",
"name": "_taskReceipts",
"type": "tuple[]"
}
],
"name": "multiCancelTasks",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{ "internalType": "address", "name": "_executor", "type": "address" },
{
"components": [
{
"internalType": "address[]",
"name": "conditions",
"type": "address[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "gasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct TaskSpec[]",
"name": "_taskSpecs",
"type": "tuple[]"
},
{ "internalType": "address[]", "name": "_modules", "type": "address[]" },
{ "internalType": "uint256", "name": "_ethToDeposit", "type": "uint256" },
{ "internalType": "uint256", "name": "_getId", "type": "uint256" },
{ "internalType": "uint256", "name": "_setId", "type": "uint256" }
],
"name": "multiProvide",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_withdrawAmount",
"type": "uint256"
},
{
"components": [
{
"internalType": "address[]",
"name": "conditions",
"type": "address[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "gasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct TaskSpec[]",
"name": "_taskSpecs",
"type": "tuple[]"
},
{ "internalType": "address[]", "name": "_modules", "type": "address[]" },
{ "internalType": "uint256", "name": "_getId", "type": "uint256" },
{ "internalType": "uint256", "name": "_setId", "type": "uint256" }
],
"name": "multiUnprovide",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"internalType": "struct Provider",
"name": "_provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct Task",
"name": "_task",
"type": "tuple"
},
{ "internalType": "uint256", "name": "_expiryDate", "type": "uint256" }
],
"name": "submitTask",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"internalType": "struct Provider",
"name": "_provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct Task[]",
"name": "_tasks",
"type": "tuple[]"
},
{ "internalType": "uint256", "name": "_expiryDate", "type": "uint256" },
{
"internalType": "uint256",
"name": "_sumOfRequestedTaskSubmits",
"type": "uint256"
}
],
"name": "submitTaskChain",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "address", "name": "module", "type": "address" }
],
"internalType": "struct Provider",
"name": "_provider",
"type": "tuple"
},
{
"components": [
{
"components": [
{ "internalType": "address", "name": "inst", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"internalType": "struct Condition[]",
"name": "conditions",
"type": "tuple[]"
},
{
"components": [
{ "internalType": "address", "name": "addr", "type": "address" },
{ "internalType": "bytes", "name": "data", "type": "bytes" },
{
"internalType": "enum Operation",
"name": "operation",
"type": "uint8"
},
{
"internalType": "enum DataFlow",
"name": "dataFlow",
"type": "uint8"
},
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bool", "name": "termsOkCheck", "type": "bool" }
],
"internalType": "struct Action[]",
"name": "actions",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "selfProviderGasLimit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "selfProviderGasPriceCeil",
"type": "uint256"
}
],
"internalType": "struct Task[]",
"name": "_tasks",
"type": "tuple[]"
},
{ "internalType": "uint256", "name": "_expiryDate", "type": "uint256" },
{ "internalType": "uint256", "name": "_cycles", "type": "uint256" }
],
"name": "submitTaskCycle",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
]

View File

@ -103,7 +103,7 @@ describe("Gas Measurements: Full Debt Bridge From Maker ETH-A to ETH-B", functio
gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
await contracts.dsa.cast(

View File

@ -102,7 +102,7 @@ describe("Gas Measurements: Full Debt Bridge From Maker ETH-A to NEW ETH-B", fun
gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
await contracts.dsa.cast(

View File

@ -31,7 +31,7 @@ module.exports = async function (mockRoute) {
await addProviderModuleDSA(
wallets.gelatoProvider,
contracts.gelatoCore,
contracts.dsaProviderModule.address
contracts.providerModuleDSA.address
);
contracts.dsa = await createDSA(
wallets.userAddress,

View File

@ -30,7 +30,7 @@ module.exports = async function (mockRoute) {
await addProviderModuleDSA(
wallets.gelatoProvider,
contracts.gelatoCore,
contracts.dsaProviderModule.address
contracts.providerModuleDSA.address
);
contracts.dsa = await createDSA(
wallets.userAddress,

View File

@ -1,4 +1,4 @@
const ConnectGelatoABI = require("../../../pre-compiles/ConnectGelato.json")
const ConnectGelatoABI = require("../../../artifacts/contracts/contracts/connectors/ConnectGelato.sol/ConnectGelato.json")
.abi;
const ConnectAuthABI = require("../../../pre-compiles/ConnectAuth.json").abi;
const ConnectMakerABI = require("../../../pre-compiles/ConnectMaker.json").abi;

View File

@ -4,7 +4,6 @@ const GelatoCoreLib = require("@gelatonetwork/core");
const InstaIndex = require("../../../pre-compiles/InstaIndex.json");
const InstaList = require("../../../pre-compiles/InstaList.json");
const ConnectGelato = require("../../../pre-compiles/ConnectGelato.json");
const ConnectMaker = require("../../../pre-compiles/ConnectMaker.json");
const ConnectCompound = require("../../../pre-compiles/ConnectCompound.json");
const ConnectInstaPool = require("../../../pre-compiles/ConnectInstaPool.json");
@ -16,7 +15,6 @@ const GetCdps = require("../../../pre-compiles/GetCdps.json");
const IERC20 = require("../../../pre-compiles/IERC20.json");
const CTokenInterface = require("../../../pre-compiles/CTokenInterface.json");
const CompoundResolver = require("../../../pre-compiles/InstaCompoundResolver.json");
const DsaProviderModuleABI = require("../../../pre-compiles/ProviderModuleDsa_ABI.json");
const InstaPoolResolver = require("../../../artifacts/contracts/interfaces/InstaDapp/resolvers/IInstaPoolResolver.sol/IInstaPoolResolver.json");
module.exports = async function () {
@ -37,10 +35,6 @@ module.exports = async function () {
InstaList.abi,
hre.network.config.InstaList
);
const connectGelato = await ethers.getContractAt(
ConnectGelato.abi,
hre.network.config.ConnectGelato
);
const connectMaker = await ethers.getContractAt(
ConnectMaker.abi,
hre.network.config.ConnectMaker
@ -82,33 +76,38 @@ module.exports = async function () {
CompoundResolver.abi,
hre.network.config.CompoundResolver
);
const dsaProviderModule = await ethers.getContractAt(
DsaProviderModuleABI,
hre.network.config.ProviderModuleDsa
);
const instaPoolResolver = await ethers.getContractAt(
InstaPoolResolver.abi,
hre.network.config.InstaPoolResolver
);
// ===== Get deployed contracts ==================
const priceOracleResolver = await ethers.getContract("PriceOracleResolver");
const conditionMakerVaultUnsafe = await ethers.getContract(
"ConditionMakerVaultUnsafe"
);
const conditionDebtBridgeIsAffordable = await ethers.getContract(
"ConditionDebtBridgeIsAffordable"
);
const connectGelatoExecutorPayment = await ethers.getContract(
"ConnectGelatoExecutorPayment"
);
const makerResolver = await ethers.getContract("MakerResolver");
const connectGelato = await ethers.getContract("ConnectGelato");
const connectGelatoDataFullMakerToMaker = await ethers.getContract(
"ConnectGelatoDataFullMakerToMaker"
);
const connectGelatoDataFullMakerToCompound = await ethers.getContract(
"ConnectGelatoDataFullMakerToCompound"
);
const connectGelatoExecutorPayment = await ethers.getContract(
"ConnectGelatoExecutorPayment"
);
const providerModuleDSA = await ethers.getContract("ProviderModuleDSA");
const conditionMakerVaultUnsafe = await ethers.getContract(
"ConditionMakerVaultUnsafe"
);
const conditionDebtBridgeIsAffordable = await ethers.getContract(
"ConditionDebtBridgeIsAffordable"
);
const conditionDestVaultWillBeSafe = await ethers.getContract(
"ConditionDestVaultWillBeSafe"
);
const priceOracleResolver = await ethers.getContract("PriceOracleResolver");
const makerResolver = await ethers.getContract("MakerResolver");
const mockDebtBridgeETHBExecutor = await ethers.getContract(
"MockDebtBridgeETHBExecutor"
);
@ -116,10 +115,6 @@ module.exports = async function () {
"MockConnectGelatoDataFullMakerToMaker"
);
const conditionDestVaultWillBeSafe = await ethers.getContract(
"ConditionDestVaultWillBeSafe"
);
return {
connectGelato,
connectMaker,
@ -145,7 +140,7 @@ module.exports = async function () {
dsa: ethers.constants.AddressZero,
makerResolver,
instaPoolResolver,
dsaProviderModule,
providerModuleDSA,
conditionDebtBridgeIsAffordable,
mockDebtBridgeETHBExecutor,
mockConnectGelatoDataFullMakerToMaker,

View File

@ -1,248 +1,248 @@
// running `npx hardhat test` automatically makes use of hardhat-waffle plugin
// => only dependency we need is "chai"
const { expect } = require("chai");
const hre = require("hardhat");
const { ethers } = hre;
const GelatoCoreLib = require("@gelatonetwork/core");
//const { sleep } = GelatoCoreLib;
// // running `npx hardhat test` automatically makes use of hardhat-waffle plugin
// // => only dependency we need is "chai"
// const { expect } = require("chai");
// const hre = require("hardhat");
// const { ethers } = hre;
// const GelatoCoreLib = require("@gelatonetwork/core");
// //const { sleep } = GelatoCoreLib;
// Constants
const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// // Constants
// const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// Contracts
const InstaIndex = require("../../pre-compiles/InstaIndex.json");
const InstaList = require("../../pre-compiles/InstaList.json");
const InstaConnectors = require("../../pre-compiles/InstaConnectors.json");
const InstaAccount = require("../../pre-compiles/InstaAccount.json");
const ConnectAuth = require("../../pre-compiles/ConnectAuth.json");
const ConnectBasic = require("../../pre-compiles/ConnectBasic.json");
const ProviderModuleDsa_ABI = require("../../pre-compiles/ProviderModuleDsa_ABI.json");
// // Contracts
// const InstaIndex = require("../../pre-compiles/InstaIndex.json");
// const InstaList = require("../../pre-compiles/InstaList.json");
// const InstaConnectors = require("../../pre-compiles/InstaConnectors.json");
// const InstaAccount = require("../../pre-compiles/InstaAccount.json");
// const ConnectAuth = require("../../pre-compiles/ConnectAuth.json");
// const ConnectBasic = require("../../pre-compiles/ConnectBasic.json");
// const ProviderModuleDSA_ABI = require("../../pre-compiles/ProviderModuleDSA_ABI.json");
describe("DSA setup with Gelato Tests", function () {
this.timeout(50000);
if (hre.network.name !== "hardhat") {
console.error("Test Suite is meant to be run on hardhat only");
process.exit(1);
}
// describe("DSA setup with Gelato Tests", function () {
// this.timeout(50000);
// if (hre.network.name !== "hardhat") {
// console.error("Test Suite is meant to be run on hardhat only");
// process.exit(1);
// }
// Wallet to use for local testing
let userWallet;
let userAddress;
let dsaAddress;
// // Wallet to use for local testing
// let userWallet;
// let userAddress;
// let dsaAddress;
// Deployed instances
let instaIndex;
let instaList;
let instaConnectors;
let instaAccount;
let gelatoCore;
let providerModuleDSA;
// // Deployed instances
// let instaIndex;
// let instaList;
// let instaConnectors;
// let instaAccount;
// let gelatoCore;
// let providerModuleDSA;
// Contracts to deploy and use for local testing
let dsa;
// // Contracts to deploy and use for local testing
// let dsa;
// Other variables
let dsaVersion;
let dsaID;
// // Other variables
// let dsaVersion;
// let dsaID;
before(async function () {
// Get Test Wallet for local testnet
[userWallet] = await ethers.getSigners();
userAddress = await userWallet.getAddress();
// before(async function () {
// // Get Test Wallet for local testnet
// [userWallet] = await ethers.getSigners();
// userAddress = await userWallet.getAddress();
// ===== DSA LOCAL SETUP ==================
instaIndex = await ethers.getContractAt(
InstaIndex.abi,
hre.network.config.InstaIndex
);
instaList = await ethers.getContractAt(
InstaList.abi,
hre.network.config.InstaList
);
instaConnectors = await ethers.getContractAt(
InstaConnectors.abi,
hre.network.config.InstaConnectors
);
instaAccount = await ethers.getContractAt(
InstaAccount.abi,
hre.network.config.InstaAccount
);
// // ===== DSA LOCAL SETUP ==================
// instaIndex = await ethers.getContractAt(
// InstaIndex.abi,
// hre.network.config.InstaIndex
// );
// instaList = await ethers.getContractAt(
// InstaList.abi,
// hre.network.config.InstaList
// );
// instaConnectors = await ethers.getContractAt(
// InstaConnectors.abi,
// hre.network.config.InstaConnectors
// );
// instaAccount = await ethers.getContractAt(
// InstaAccount.abi,
// hre.network.config.InstaAccount
// );
dsaVersion = await instaAccount.version();
dsaID = await instaList.accounts();
// dsaVersion = await instaAccount.version();
// dsaID = await instaList.accounts();
// Deploy DSA and get and verify ID of newly deployed DSA
await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit(
instaIndex,
"LogAccountCreated"
);
await expect(await instaList.accounts()).to.be.equal(dsaID.add(1));
dsaID = dsaID.add(1);
// // Deploy DSA and get and verify ID of newly deployed DSA
// await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit(
// instaIndex,
// "LogAccountCreated"
// );
// await expect(await instaList.accounts()).to.be.equal(dsaID.add(1));
// dsaID = dsaID.add(1);
// Instantiate the DSA
dsaAddress = await instaList.accountAddr(dsaID);
dsa = await ethers.getContractAt(InstaAccount.abi, dsaAddress);
// // Instantiate the DSA
// dsaAddress = await instaList.accountAddr(dsaID);
// dsa = await ethers.getContractAt(InstaAccount.abi, dsaAddress);
// ===== GELATO LOCAL SETUP ==================
gelatoCore = await ethers.getContractAt(
GelatoCoreLib.GelatoCore.abi,
hre.network.config.GelatoCore
);
providerModuleDSA = await ethers.getContractAt(
ProviderModuleDsa_ABI,
hre.network.config.ProviderModuleDsa
);
});
// // ===== GELATO LOCAL SETUP ==================
// gelatoCore = await ethers.getContractAt(
// GelatoCoreLib.GelatoCore.abi,
// hre.network.config.GelatoCore
// );
// providerModuleDSA = await ethers.getContractAt(
// ProviderModuleDSA_ABI,
// hre.network.config.ProviderModuleDSA
// );
// });
it("#1: Forks InstaDapp Mainnet config", async function () {
expect(await instaIndex.list()).to.be.equal(instaList.address);
expect(dsaVersion).to.be.equal(1);
expect(await instaIndex.connectors(dsaVersion)).to.be.equal(
instaConnectors.address
);
expect(await instaConnectors.connectors(hre.network.config.ConnectAuth)).to
.be.true;
expect(await instaConnectors.connectors(hre.network.config.ConnectBasic)).to
.be.true;
expect(await instaConnectors.connectors(hre.network.config.ConnectMaker)).to
.be.true;
expect(await instaConnectors.connectors(hre.network.config.ConnectCompound))
.to.be.true;
});
// it("#1: Forks InstaDapp Mainnet config", async function () {
// expect(await instaIndex.list()).to.be.equal(instaList.address);
// expect(dsaVersion).to.be.equal(1);
// expect(await instaIndex.connectors(dsaVersion)).to.be.equal(
// instaConnectors.address
// );
// expect(await instaConnectors.connectors(hre.network.config.ConnectAuth)).to
// .be.true;
// expect(await instaConnectors.connectors(hre.network.config.ConnectBasic)).to
// .be.true;
// expect(await instaConnectors.connectors(hre.network.config.ConnectMaker)).to
// .be.true;
// expect(await instaConnectors.connectors(hre.network.config.ConnectCompound))
// .to.be.true;
// });
it("#2: Deploys a DSA with user as authority", async function () {
expect(await dsa.isAuth(userAddress)).to.be.true;
});
// it("#2: Deploys a DSA with user as authority", async function () {
// expect(await dsa.isAuth(userAddress)).to.be.true;
// });
it("#3: Let's User deposit and withdraw funds from DSA", async function () {
// Send withdraw TX via DSA.cast delegatecall
const gasLimit = ethers.BigNumber.from(1000000);
const gasPrice = ethers.utils.parseUnits("20", "gwei");
const gasCostMax = gasLimit.mul(gasPrice);
// it("#3: Let's User deposit and withdraw funds from DSA", async function () {
// // Send withdraw TX via DSA.cast delegatecall
// const gasLimit = ethers.BigNumber.from(1000000);
// const gasPrice = ethers.utils.parseUnits("20", "gwei");
// const gasCostMax = gasLimit.mul(gasPrice);
// Deposit funds into DSA
const initialWalletBalance = await userWallet.getBalance();
expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
await userWallet.sendTransaction({
to: dsaAddress,
value: ethers.utils.parseEther("1"),
gasLimit,
gasPrice,
});
expect(await userWallet.getBalance()).to.be.lt(
initialWalletBalance.sub(ethers.utils.parseEther("1"))
);
expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(
ethers.utils.parseEther("1")
);
// // Deposit funds into DSA
// const initialWalletBalance = await userWallet.getBalance();
// expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
// await userWallet.sendTransaction({
// to: dsaAddress,
// value: ethers.utils.parseEther("1"),
// gasLimit,
// gasPrice,
// });
// expect(await userWallet.getBalance()).to.be.lt(
// initialWalletBalance.sub(ethers.utils.parseEther("1"))
// );
// expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(
// ethers.utils.parseEther("1")
// );
// Encode Payloads for ConnectBasic.withdraw
const withdrawData = await hre.run("abi-encode-withselector", {
abi: ConnectBasic.abi,
functionname: "withdraw",
inputs: [ETH, ethers.utils.parseEther("1"), userAddress, 0, 0],
});
// // Encode Payloads for ConnectBasic.withdraw
// const withdrawData = await hre.run("abi-encode-withselector", {
// abi: ConnectBasic.abi,
// functionname: "withdraw",
// inputs: [ETH, ethers.utils.parseEther("1"), userAddress, 0, 0],
// });
await expect(
dsa.cast([hre.network.config.ConnectBasic], [withdrawData], userAddress, {
gasLimit,
gasPrice,
})
)
.to.emit(dsa, "LogCast")
.withArgs(userAddress, userAddress, 0);
// await expect(
// dsa.cast([hre.network.config.ConnectBasic], [withdrawData], userAddress, {
// gasLimit,
// gasPrice,
// })
// )
// .to.emit(dsa, "LogCast")
// .withArgs(userAddress, userAddress, 0);
expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
expect(await userWallet.getBalance()).to.be.gte(
initialWalletBalance.sub(gasCostMax.mul(2))
);
});
// expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
// expect(await userWallet.getBalance()).to.be.gte(
// initialWalletBalance.sub(gasCostMax.mul(2))
// );
// });
it("#4: Enables GelatoCore as a User of the DSA", async function () {
expect(await dsa.isAuth(gelatoCore.address)).to.be.false;
// it("#4: Enables GelatoCore as a User of the DSA", async function () {
// expect(await dsa.isAuth(gelatoCore.address)).to.be.false;
// Encode Payloads for ConnectAuth.addModule
const addAuthData = await hre.run("abi-encode-withselector", {
abi: ConnectAuth.abi,
functionname: "add",
inputs: [gelatoCore.address],
});
// // Encode Payloads for ConnectAuth.addModule
// const addAuthData = await hre.run("abi-encode-withselector", {
// abi: ConnectAuth.abi,
// functionname: "add",
// inputs: [gelatoCore.address],
// });
await expect(
dsa.cast([hre.network.config.ConnectAuth], [addAuthData], userAddress)
)
.to.emit(dsa, "LogCast")
.withArgs(userAddress, userAddress, 0);
// await expect(
// dsa.cast([hre.network.config.ConnectAuth], [addAuthData], userAddress)
// )
// .to.emit(dsa, "LogCast")
// .withArgs(userAddress, userAddress, 0);
expect(await dsa.isAuth(gelatoCore.address)).to.be.true;
});
// expect(await dsa.isAuth(gelatoCore.address)).to.be.true;
// });
it("#5: ConnectGelato is deployed and whitelisted on mainnet", async function () {
expect(
await instaConnectors.isConnector([hre.network.config.ConnectGelato])
).to.be.true;
});
// it("#5: ConnectGelato is deployed and whitelisted on mainnet", async function () {
// expect(
// await instaConnectors.isConnector([hre.network.config.ConnectGelato])
// ).to.be.true;
// });
it("#6: Gelato ProviderModuleDsa returns correct execPayload", async function () {
// Deposit 1 ETH into DSA
await userWallet.sendTransaction({
to: dsaAddress,
value: ethers.utils.parseEther("1"),
});
expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(
ethers.utils.parseEther("1")
);
// it("#6: Gelato ProviderModuleDSA returns correct execPayload", async function () {
// // Deposit 1 ETH into DSA
// await userWallet.sendTransaction({
// to: dsaAddress,
// value: ethers.utils.parseEther("1"),
// });
// expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(
// ethers.utils.parseEther("1")
// );
// We withdraw to otherWallet to ignore gasUsed during test
const { 1: otherWallet } = await ethers.getSigners();
// // We withdraw to otherWallet to ignore gasUsed during test
// const { 1: otherWallet } = await ethers.getSigners();
// Instantiate Gelato ConnectBasic.withdraw Task
const withdrawFromDSATask = new GelatoCoreLib.Task({
actions: [
new GelatoCoreLib.Action({
addr: hre.network.config.ConnectBasic,
data: await hre.run("abi-encode-withselector", {
abi: ConnectBasic.abi,
functionname: "withdraw",
inputs: [
ETH,
ethers.utils.parseEther("1"),
await otherWallet.getAddress(),
0,
0,
],
}),
operation: GelatoCoreLib.Operation.Delegatecall, // placeholder
}),
],
});
// // Instantiate Gelato ConnectBasic.withdraw Task
// const withdrawFromDSATask = new GelatoCoreLib.Task({
// actions: [
// new GelatoCoreLib.Action({
// addr: hre.network.config.ConnectBasic,
// data: await hre.run("abi-encode-withselector", {
// abi: ConnectBasic.abi,
// functionname: "withdraw",
// inputs: [
// ETH,
// ethers.utils.parseEther("1"),
// await otherWallet.getAddress(),
// 0,
// 0,
// ],
// }),
// operation: GelatoCoreLib.Operation.Delegatecall, // placeholder
// }),
// ],
// });
// otherWallet needs to be an authority to qualify as withdraw to address.
const addAuthData = await hre.run("abi-encode-withselector", {
abi: ConnectAuth.abi,
functionname: "add",
inputs: [await otherWallet.getAddress()],
});
await dsa.cast(
[hre.network.config.ConnectAuth],
[addAuthData],
userAddress
);
// // otherWallet needs to be an authority to qualify as withdraw to address.
// const addAuthData = await hre.run("abi-encode-withselector", {
// abi: ConnectAuth.abi,
// functionname: "add",
// inputs: [await otherWallet.getAddress()],
// });
// await dsa.cast(
// [hre.network.config.ConnectAuth],
// [addAuthData],
// userAddress
// );
const [execPayload] = await providerModuleDSA.execPayload(
0, // placeholder
ethers.constants.AddressZero, // placeholder
ethers.constants.AddressZero, // placeholder
withdrawFromDSATask,
0 // placeholder
);
// const [execPayload] = await providerModuleDSA.execPayload(
// 0, // placeholder
// ethers.constants.AddressZero, // placeholder
// ethers.constants.AddressZero, // placeholder
// withdrawFromDSATask,
// 0 // placeholder
// );
await expect(() =>
userWallet.sendTransaction({
to: dsaAddress,
data: execPayload,
})
).to.changeBalance(otherWallet, ethers.utils.parseEther("1"));
expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
});
});
// await expect(() =>
// userWallet.sendTransaction({
// to: dsaAddress,
// data: execPayload,
// })
// ).to.changeBalance(otherWallet, ethers.utils.parseEther("1"));
// expect(await ethers.provider.getBalance(dsaAddress)).to.be.equal(0);
// });
// });

View File

@ -111,7 +111,7 @@ describe("Full Debt Bridge refinancing loan from Maker to Compound", function ()
const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
const expiryDate = 0;

View File

@ -124,7 +124,7 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B with vault creat
const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
const expiryDate = 0;

View File

@ -126,7 +126,7 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B", function () {
const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
const expiryDate = 0;

View File

@ -126,7 +126,7 @@ describe("Full Debt Bridge refinancing loan from ETH-A to ETH-B with Vault B cre
const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
const expiryDate = 0;

View File

@ -32,7 +32,7 @@ module.exports = async function () {
await addProviderModuleDSA(
wallets.gelatoProvider,
contracts.gelatoCore,
contracts.dsaProviderModule.address
contracts.providerModuleDSA.address
);
contracts.dsa = await createDSA(
wallets.userAddress,

View File

@ -33,7 +33,7 @@ module.exports = async function () {
await addProviderModuleDSA(
wallets.gelatoProvider,
contracts.gelatoCore,
contracts.dsaProviderModule.address
contracts.providerModuleDSA.address
);
contracts.dsa = await createDSA(
wallets.userAddress,

View File

@ -32,7 +32,7 @@ module.exports = async function () {
await addProviderModuleDSA(
wallets.gelatoProvider,
contracts.gelatoCore,
contracts.dsaProviderModule.address
contracts.providerModuleDSA.address
);
contracts.dsa = await createDSA(
wallets.userAddress,

View File

@ -124,7 +124,7 @@ describe("Security: _cast function by example of ETHA-ETHB with disabled Connect
const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
addr: wallets.gelatoProviderAddress, // Gelato Provider Address
module: contracts.dsaProviderModule.address, // Gelato DSA module
module: contracts.providerModuleDSA.address, // Gelato DSA module
});
const expiryDate = 0;

View File

@ -148,7 +148,7 @@
// let connectGelatoPartialDebtBridgeFromMaker;
// let connectGelatoExecutorPayment;
// let priceOracleResolver;
// let dsaProviderModule;
// let providerModuleDSA;
// // Creation during test
// let dsa;
@ -268,14 +268,14 @@
// );
// await connectGelatoExecutorPayment.deployed();
// const ProviderModuleDsa = await ethers.getContractFactory(
// "ProviderModuleDsa"
// const ProviderModuleDSA = await ethers.getContractFactory(
// "ProviderModuleDSA"
// );
// dsaProviderModule = await ProviderModuleDsa.deploy(
// providerModuleDSA = await ProviderModuleDSA.deploy(
// hre.network.config.GelatoCore,
// connectGelatoExecutorPayment.address
// );
// await dsaProviderModule.deployed();
// await providerModuleDSA.deployed();
// ///////////////////////////////////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -426,13 +426,13 @@
// await expect(
// gelatoCore
// .connect(gelatoProvider)
// .addProviderModules([dsaProviderModule.address])
// .addProviderModules([providerModuleDSA.address])
// ).to.emit(gelatoCore, "LogProviderModuleAdded");
// expect(
// await gelatoCore
// .connect(gelatoProvider)
// .isModuleProvided(gelatoProviderAddress, dsaProviderModule.address)
// .isModuleProvided(gelatoProviderAddress, providerModuleDSA.address)
// ).to.be.true;
// //#endregion
@ -726,7 +726,7 @@
// const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({
// addr: gelatoProviderAddress,
// module: dsaProviderModule.address,
// module: providerModuleDSA.address,
// });
// const expiryDate = 0;

View File

@ -1,396 +1,397 @@
// running `npx hardhat test` automatically makes use of hardhat-waffle plugin
// => only dependency we need is "chai"
const { expect } = require("chai");
const hre = require("hardhat");
const { deployments, ethers } = hre;
// // running `npx hardhat test` automatically makes use of hardhat-waffle plugin
// // => only dependency we need is "chai"
// const { expect } = require("chai");
// const hre = require("hardhat");
// const { deployments, ethers } = hre;
const GelatoCoreLib = require("@gelatonetwork/core");
//const { sleep } = GelatoCoreLib;
// const GelatoCoreLib = require("@gelatonetwork/core");
// //const { sleep } = GelatoCoreLib;
// Constants
const DAI_100 = ethers.utils.parseUnits("100", 18);
// // Constants
// const DAI_100 = ethers.utils.parseUnits("100", 18);
// Contracts
const InstaIndex = require("../../../pre-compiles/InstaIndex.json");
const InstaList = require("../../../pre-compiles/InstaList.json");
const InstaAccount = require("../../../pre-compiles/InstaAccount.json");
const ConnectAuth = require("../../../pre-compiles/ConnectAuth.json");
const ConnectGelato_ABI = require("../../../pre-compiles/ConnectGelato_ABI.json");
const ConnectMaker = require("../../../pre-compiles/ConnectMaker.json");
const ConnectCompound = require("../../../pre-compiles/ConnectCompound.json");
const IERC20 = require("../../../pre-compiles/IERC20.json");
const IUniswapExchange = require("../../../pre-compiles/IUniswapExchange.json");
// // Contracts
// const InstaIndex = require("../../../pre-compiles/InstaIndex.json");
// const InstaList = require("../../../pre-compiles/InstaList.json");
// const InstaAccount = require("../../../pre-compiles/InstaAccount.json");
// const ConnectAuth = require("../../../pre-compiles/ConnectAuth.json");
// const ConnectGelato_ABI = require("../../../artifacts/contracts/contracts/connectors/ConnectGelato.sol/ConnectGelato.json")
// .abi;
// const ConnectMaker = require("../../../pre-compiles/ConnectMaker.json");
// const ConnectCompound = require("../../../pre-compiles/ConnectCompound.json");
// const IERC20 = require("../../../pre-compiles/IERC20.json");
// const IUniswapExchange = require("../../../pre-compiles/IUniswapExchange.json");
describe("Move DAI lending from DSR to Compound", function () {
this.timeout(0);
if (hre.network.name !== "hardhat") {
console.error("Test Suite is meant to be run on hardhat only");
process.exit(1);
}
// describe("Move DAI lending from DSR to Compound", function () {
// this.timeout(0);
// if (hre.network.name !== "hardhat") {
// console.error("Test Suite is meant to be run on hardhat only");
// process.exit(1);
// }
// Wallet to use for local testing
let userWallet;
let userAddress;
let dsaAddress;
// // Wallet to use for local testing
// let userWallet;
// let userAddress;
// let dsaAddress;
// Deployed instances
let connectMaker;
let connectCompound;
let gelatoCore;
let dai;
// // Deployed instances
// let connectMaker;
// let connectCompound;
// let gelatoCore;
// let dai;
// Contracts to deploy and use for local testing
let dsa;
let mockDSR;
let mockCDAI;
let conditionCompareUints;
// // Contracts to deploy and use for local testing
// let dsa;
// let mockDSR;
// let mockCDAI;
// let conditionCompareUints;
before(async function () {
// Reset back to a fresh forked state during runtime
await deployments.fixture();
// before(async function () {
// // Reset back to a fresh forked state during runtime
// await deployments.fixture();
// Get Test Wallet for local testnet
[userWallet] = await ethers.getSigners();
userAddress = await userWallet.getAddress();
// // 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")
);
// // Hardhat default accounts prefilled with 100 ETH
// expect(await userWallet.getBalance()).to.be.gt(
// ethers.utils.parseEther("10")
// );
// ===== DSA SETUP ==================
const instaIndex = await ethers.getContractAt(
InstaIndex.abi,
hre.network.config.InstaIndex
);
const instaList = await ethers.getContractAt(
InstaList.abi,
hre.network.config.InstaList
);
connectMaker = await ethers.getContractAt(
ConnectMaker.abi,
hre.network.config.ConnectMaker
);
connectCompound = await ethers.getContractAt(
ConnectCompound.abi,
hre.network.config.ConnectCompound
);
// // ===== DSA SETUP ==================
// const instaIndex = await ethers.getContractAt(
// InstaIndex.abi,
// hre.network.config.InstaIndex
// );
// const instaList = await ethers.getContractAt(
// InstaList.abi,
// hre.network.config.InstaList
// );
// connectMaker = await ethers.getContractAt(
// ConnectMaker.abi,
// hre.network.config.ConnectMaker
// );
// connectCompound = await ethers.getContractAt(
// ConnectCompound.abi,
// hre.network.config.ConnectCompound
// );
// Deploy DSA and get and verify ID of newly deployed DSA
const dsaIDPrevious = await instaList.accounts();
await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit(
instaIndex,
"LogAccountCreated"
);
const dsaID = dsaIDPrevious.add(1);
await expect(await instaList.accounts()).to.be.equal(dsaID);
// // Deploy DSA and get and verify ID of newly deployed DSA
// const dsaIDPrevious = await instaList.accounts();
// await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit(
// instaIndex,
// "LogAccountCreated"
// );
// const dsaID = dsaIDPrevious.add(1);
// await expect(await instaList.accounts()).to.be.equal(dsaID);
// Instantiate the DSA
dsaAddress = await instaList.accountAddr(dsaID);
dsa = await ethers.getContractAt(InstaAccount.abi, dsaAddress);
// // Instantiate the DSA
// dsaAddress = await instaList.accountAddr(dsaID);
// dsa = await ethers.getContractAt(InstaAccount.abi, dsaAddress);
// ===== GELATO SETUP ==================
gelatoCore = await ethers.getContractAt(
GelatoCoreLib.GelatoCore.abi,
hre.network.config.GelatoCore
);
// // ===== GELATO SETUP ==================
// gelatoCore = await ethers.getContractAt(
// GelatoCoreLib.GelatoCore.abi,
// hre.network.config.GelatoCore
// );
// Add GelatoCore as auth on DSA
const addAuthData = await hre.run("abi-encode-withselector", {
abi: ConnectAuth.abi,
functionname: "add",
inputs: [gelatoCore.address],
});
await dsa.cast(
[hre.network.config.ConnectAuth],
[addAuthData],
userAddress
);
expect(await dsa.isAuth(gelatoCore.address)).to.be.true;
// // Add GelatoCore as auth on DSA
// const addAuthData = await hre.run("abi-encode-withselector", {
// abi: ConnectAuth.abi,
// functionname: "add",
// inputs: [gelatoCore.address],
// });
// await dsa.cast(
// [hre.network.config.ConnectAuth],
// [addAuthData],
// userAddress
// );
// expect(await dsa.isAuth(gelatoCore.address)).to.be.true;
// Deployed Mocks for Testing
mockCDAI = await ethers.getContract("MockCDAI");
mockDSR = await ethers.getContract("MockDSR");
// // Deployed Mocks for Testing
// mockCDAI = await ethers.getContract("MockCDAI");
// mockDSR = await ethers.getContract("MockDSR");
// Deployed Gelato Conditions for Testing
conditionCompareUints = await ethers.getContract(
"ConditionCompareUintsFromTwoSources"
);
// // Deployed Gelato Conditions for Testing
// conditionCompareUints = await ethers.getContract(
// "ConditionCompareUintsFromTwoSources"
// );
// ===== Dapp Dependencies SETUP ==================
// This test assumes our user has 100 DAI deposited in Maker DSR
dai = await ethers.getContractAt(IERC20.abi, hre.network.config.DAI);
expect(await dai.balanceOf(userAddress)).to.be.equal(0);
// // ===== Dapp Dependencies SETUP ==================
// // This test assumes our user has 100 DAI deposited in Maker DSR
// dai = await ethers.getContractAt(IERC20.abi, hre.network.config.DAI);
// expect(await dai.balanceOf(userAddress)).to.be.equal(0);
// Let's get the test user 100 DAI++ from Kyber
const daiUniswapExchange = await ethers.getContractAt(
IUniswapExchange.abi,
hre.network.config.DAI_UNISWAP
);
await daiUniswapExchange.ethToTokenTransferInput(
1,
2525644800, // random timestamp in the future (year 2050)
userAddress,
{
value: ethers.utils.parseEther("2"),
}
);
expect(await dai.balanceOf(userAddress)).to.be.gte(DAI_100);
// // Let's get the test user 100 DAI++ from Kyber
// const daiUniswapExchange = await ethers.getContractAt(
// IUniswapExchange.abi,
// hre.network.config.DAI_UNISWAP
// );
// await daiUniswapExchange.ethToTokenTransferInput(
// 1,
// 2525644800, // random timestamp in the future (year 2050)
// userAddress,
// {
// value: ethers.utils.parseEther("2"),
// }
// );
// expect(await dai.balanceOf(userAddress)).to.be.gte(DAI_100);
// Next we transfer the 100 DAI into our DSA
await dai.transfer(dsa.address, DAI_100);
expect(await dai.balanceOf(dsa.address)).to.be.eq(DAI_100);
// // Next we transfer the 100 DAI into our DSA
// await dai.transfer(dsa.address, DAI_100);
// expect(await dai.balanceOf(dsa.address)).to.be.eq(DAI_100);
// Next we deposit the 100 DAI into the DSR
const depositDai = await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "depositDai",
inputs: [DAI_100, 0, 0],
});
// // Next we deposit the 100 DAI into the DSR
// const depositDai = await hre.run("abi-encode-withselector", {
// abi: ConnectMaker.abi,
// functionname: "depositDai",
// inputs: [DAI_100, 0, 0],
// });
await expect(
dsa.cast([hre.network.config.ConnectMaker], [depositDai], userAddress)
)
.to.emit(dsa, "LogCast")
.withArgs(userAddress, userAddress, 0);
expect(await dai.balanceOf(dsa.address)).to.be.eq(0);
});
// await expect(
// dsa.cast([hre.network.config.ConnectMaker], [depositDai], userAddress)
// )
// .to.emit(dsa, "LogCast")
// .withArgs(userAddress, userAddress, 0);
// expect(await dai.balanceOf(dsa.address)).to.be.eq(0);
// });
it("#1: Gelato refinances DAI from DSR=>Compound, if better rate", async function () {
// ======= Condition setup ======
// We instantiate the Rebalance Condition:
// Compound APY needs to be 10000000 per second points higher than DSR
const MIN_SPREAD = "10000000";
const rebalanceCondition = new GelatoCoreLib.Condition({
inst: conditionCompareUints.address,
data: await conditionCompareUints.getConditionData(
mockCDAI.address, // We are in DSR so we compare against CDAI => SourceA=CDAI
mockDSR.address, // SourceB=DSR
await hre.run("abi-encode-withselector", {
abi: (await hre.artifacts.readArtifact("MockCDAI")).abi,
functionname: "supplyRatePerSecond",
}), // CDAI data feed first (sourceAData)
await hre.run("abi-encode-withselector", {
abi: (await hre.artifacts.readArtifact("MockDSR")).abi,
functionname: "dsr",
}), // DSR data feed second (sourceBData)
MIN_SPREAD
),
});
// it("#1: Gelato refinances DAI from DSR=>Compound, if better rate", async function () {
// // ======= Condition setup ======
// // We instantiate the Rebalance Condition:
// // Compound APY needs to be 10000000 per second points higher than DSR
// const MIN_SPREAD = "10000000";
// const rebalanceCondition = new GelatoCoreLib.Condition({
// inst: conditionCompareUints.address,
// data: await conditionCompareUints.getConditionData(
// mockCDAI.address, // We are in DSR so we compare against CDAI => SourceA=CDAI
// mockDSR.address, // SourceB=DSR
// await hre.run("abi-encode-withselector", {
// abi: (await hre.artifacts.readArtifact("MockCDAI")).abi,
// functionname: "supplyRatePerSecond",
// }), // CDAI data feed first (sourceAData)
// await hre.run("abi-encode-withselector", {
// abi: (await hre.artifacts.readArtifact("MockDSR")).abi,
// functionname: "dsr",
// }), // DSR data feed second (sourceBData)
// MIN_SPREAD
// ),
// });
// ======= Action/Spells setup ======
// To assimilate to DSA SDK
const spells = [];
// // ======= Action/Spells setup ======
// // To assimilate to DSA SDK
// const spells = [];
// We instantiate target1: Withdraw DAI from DSR and setId 1 for
// target2 Compound deposit to fetch DAI amount.
const connectorWithdrawFromDSR = new GelatoCoreLib.Action({
addr: connectMaker.address,
data: await hre.run("abi-encode-withselector", {
abi: ConnectMaker.abi,
functionname: "withdrawDai",
inputs: [ethers.constants.MaxUint256, 0, 1],
}),
operation: GelatoCoreLib.Operation.Delegatecall,
});
spells.push(connectorWithdrawFromDSR);
// // We instantiate target1: Withdraw DAI from DSR and setId 1 for
// // target2 Compound deposit to fetch DAI amount.
// const connectorWithdrawFromDSR = new GelatoCoreLib.Action({
// addr: connectMaker.address,
// data: await hre.run("abi-encode-withselector", {
// abi: ConnectMaker.abi,
// functionname: "withdrawDai",
// inputs: [ethers.constants.MaxUint256, 0, 1],
// }),
// operation: GelatoCoreLib.Operation.Delegatecall,
// });
// spells.push(connectorWithdrawFromDSR);
// We instantiate target2: Deposit DAI to CDAI and getId 1
const connectorDepositCompound = new GelatoCoreLib.Action({
addr: connectCompound.address,
data: await hre.run("abi-encode-withselector", {
abi: ConnectCompound.abi,
functionname: "deposit",
inputs: [dai.address, 0, 1, 0],
}),
operation: GelatoCoreLib.Operation.Delegatecall,
});
spells.push(connectorDepositCompound);
// // We instantiate target2: Deposit DAI to CDAI and getId 1
// const connectorDepositCompound = new GelatoCoreLib.Action({
// addr: connectCompound.address,
// data: await hre.run("abi-encode-withselector", {
// abi: ConnectCompound.abi,
// functionname: "deposit",
// inputs: [dai.address, 0, 1, 0],
// }),
// operation: GelatoCoreLib.Operation.Delegatecall,
// });
// spells.push(connectorDepositCompound);
// ======= Gelato Task Setup =========
// A Gelato Task just combines Conditions with Actions
// You also specify how much GAS a Task consumes at max and the ceiling
// gas price under which you are willing to auto-transact. There is only
// one gas price in the current Gelato system: fast gwei read from Chainlink.
const GAS_LIMIT = "4000000";
const GAS_PRICE_CEIL = ethers.utils.parseUnits("1000", "gwei");
const taskRebalanceDSRToCDAIifBetter = new GelatoCoreLib.Task({
conditions: [rebalanceCondition],
actions: spells,
selfProviderGasLimit: GAS_LIMIT,
selfProviderGasPriceCeil: GAS_PRICE_CEIL,
});
// // ======= Gelato Task Setup =========
// // A Gelato Task just combines Conditions with Actions
// // You also specify how much GAS a Task consumes at max and the ceiling
// // gas price under which you are willing to auto-transact. There is only
// // one gas price in the current Gelato system: fast gwei read from Chainlink.
// const GAS_LIMIT = "4000000";
// const GAS_PRICE_CEIL = ethers.utils.parseUnits("1000", "gwei");
// const taskRebalanceDSRToCDAIifBetter = new GelatoCoreLib.Task({
// conditions: [rebalanceCondition],
// actions: spells,
// selfProviderGasLimit: GAS_LIMIT,
// selfProviderGasPriceCeil: GAS_PRICE_CEIL,
// });
// ======= Gelato Provider setup ======
// Someone needs to pay for gas for automatic Task execution on Gelato.
// Gelato has the concept of a "Provider" to denote who is providing (depositing)
// ETH on Gelato in order to pay for automation gas. In our case, the User
// is paying for his own automation gas. Therefore, the User is a "Self-Provider".
// But since Gelato only talks to smart contract accounts, the User's DSA proxy
// plays the part of the "Self-Provider" on behalf of the User behind the DSA.
// A GelatoProvider is an object with the address of the provider - in our case
// the DSA address - and the address of the "ProviderModule". This module
// fulfills certain functions like encoding the execution payload for the Gelato
// protocol. Check out ./contracts/ProviderModuleDsa.sol to see what it does.
const gelatoSelfProvider = new GelatoCoreLib.GelatoProvider({
addr: dsa.address,
module: hre.network.config.ProviderModuleDsa,
});
// // ======= Gelato Provider setup ======
// // Someone needs to pay for gas for automatic Task execution on Gelato.
// // Gelato has the concept of a "Provider" to denote who is providing (depositing)
// // ETH on Gelato in order to pay for automation gas. In our case, the User
// // is paying for his own automation gas. Therefore, the User is a "Self-Provider".
// // But since Gelato only talks to smart contract accounts, the User's DSA proxy
// // plays the part of the "Self-Provider" on behalf of the User behind the DSA.
// // A GelatoProvider is an object with the address of the provider - in our case
// // the DSA address - and the address of the "ProviderModule". This module
// // fulfills certain functions like encoding the execution payload for the Gelato
// // protocol. Check out ./contracts/ProviderModuleDSA.sol to see what it does.
// const gelatoSelfProvider = new GelatoCoreLib.GelatoProvider({
// addr: dsa.address,
// module: hre.network.config.ProviderModuleDSA,
// });
// ======= Executor Setup =========
// For local Testing purposes our test User account will play the role of the Gelato
// Executor network because this logic is non-trivial to fork into a local instance
await gelatoCore.stakeExecutor({
value: await gelatoCore.minExecutorStake(),
});
expect(await gelatoCore.isExecutorMinStaked(userAddress)).to.be.true;
// // ======= Executor Setup =========
// // For local Testing purposes our test User account will play the role of the Gelato
// // Executor network because this logic is non-trivial to fork into a local instance
// await gelatoCore.stakeExecutor({
// value: await gelatoCore.minExecutorStake(),
// });
// expect(await gelatoCore.isExecutorMinStaked(userAddress)).to.be.true;
// ======= Gelato Task Provision =========
// Gelato requires some initial setup via its multiProvide API
// We must 1) provide ETH to pay for future automation gas, 2) we must
// assign an Executor network to the Task, 3) we must tell Gelato what
// "ProviderModule" we want to use for our Task.
// Since our DSA proxy is the one through which we interact with Gelato,
// we must do this setup via the DSA proxy by using ConnectGelato
const TASK_AUTOMATION_FUNDS = await gelatoCore.minExecProviderFunds(
GAS_LIMIT,
GAS_PRICE_CEIL
);
await dsa.cast(
[hre.network.config.ConnectGelato], // targets
[
await hre.run("abi-encode-withselector", {
abi: ConnectGelato_ABI,
functionname: "multiProvide",
inputs: [
userAddress,
[],
[hre.network.config.ProviderModuleDsa],
TASK_AUTOMATION_FUNDS,
0, // _getId
0, // _setId
],
}),
], // datas
userAddress, // origin
{
value: TASK_AUTOMATION_FUNDS,
gasLimit: 5000000,
}
);
expect(await gelatoCore.providerFunds(dsa.address)).to.be.gte(
TASK_AUTOMATION_FUNDS
);
expect(
await gelatoCore.isProviderLiquid(dsa.address, GAS_LIMIT, GAS_PRICE_CEIL)
);
expect(await gelatoCore.executorByProvider(dsa.address)).to.be.equal(
userAddress
);
expect(
await gelatoCore.isModuleProvided(
dsa.address,
hre.network.config.ProviderModuleDsa
)
).to.be.true;
// // ======= Gelato Task Provision =========
// // Gelato requires some initial setup via its multiProvide API
// // We must 1) provide ETH to pay for future automation gas, 2) we must
// // assign an Executor network to the Task, 3) we must tell Gelato what
// // "ProviderModule" we want to use for our Task.
// // Since our DSA proxy is the one through which we interact with Gelato,
// // we must do this setup via the DSA proxy by using ConnectGelato
// const TASK_AUTOMATION_FUNDS = await gelatoCore.minExecProviderFunds(
// GAS_LIMIT,
// GAS_PRICE_CEIL
// );
// await dsa.cast(
// [hre.network.config.ConnectGelato], // targets
// [
// await hre.run("abi-encode-withselector", {
// abi: ConnectGelato_ABI,
// functionname: "multiProvide",
// inputs: [
// userAddress,
// [],
// [hre.network.config.ProviderModuleDSA],
// TASK_AUTOMATION_FUNDS,
// 0, // _getId
// 0, // _setId
// ],
// }),
// ], // datas
// userAddress, // origin
// {
// value: TASK_AUTOMATION_FUNDS,
// gasLimit: 5000000,
// }
// );
// expect(await gelatoCore.providerFunds(dsa.address)).to.be.gte(
// TASK_AUTOMATION_FUNDS
// );
// expect(
// await gelatoCore.isProviderLiquid(dsa.address, GAS_LIMIT, GAS_PRICE_CEIL)
// );
// expect(await gelatoCore.executorByProvider(dsa.address)).to.be.equal(
// userAddress
// );
// expect(
// await gelatoCore.isModuleProvided(
// dsa.address,
// hre.network.config.ProviderModuleDSA
// )
// ).to.be.true;
// ======= 📣 TASK SUBMISSION 📣 =========
// In Gelato world our DSA is the User. So we must submit the Task
// to Gelato via our DSA and hence use ConnectGelato again.
const expiryDate = 0;
await expect(
dsa.cast(
[hre.network.config.ConnectGelato], // targets
[
await hre.run("abi-encode-withselector", {
abi: ConnectGelato_ABI,
functionname: "submitTask",
inputs: [
gelatoSelfProvider,
taskRebalanceDSRToCDAIifBetter,
expiryDate,
],
}),
], // datas
userAddress, // origin
{
gasLimit: 5000000,
}
)
).to.emit(gelatoCore, "LogTaskSubmitted");
// // ======= 📣 TASK SUBMISSION 📣 =========
// // In Gelato world our DSA is the User. So we must submit the Task
// // to Gelato via our DSA and hence use ConnectGelato again.
// const expiryDate = 0;
// await expect(
// dsa.cast(
// [hre.network.config.ConnectGelato], // targets
// [
// await hre.run("abi-encode-withselector", {
// abi: ConnectGelato_ABI,
// functionname: "submitTask",
// inputs: [
// gelatoSelfProvider,
// taskRebalanceDSRToCDAIifBetter,
// expiryDate,
// ],
// }),
// ], // datas
// userAddress, // origin
// {
// gasLimit: 5000000,
// }
// )
// ).to.emit(gelatoCore, "LogTaskSubmitted");
// Task Receipt: a successfully submitted Task in Gelato
// is wrapped in a TaskReceipt. For testing we instantiate the TaskReceipt
// for our to be submitted Task.
const taskReceiptId = await gelatoCore.currentTaskReceiptId();
const taskReceipt = new GelatoCoreLib.TaskReceipt({
id: taskReceiptId,
userProxy: dsa.address,
provider: gelatoSelfProvider,
tasks: [taskRebalanceDSRToCDAIifBetter],
expiryDate,
});
// // Task Receipt: a successfully submitted Task in Gelato
// // is wrapped in a TaskReceipt. For testing we instantiate the TaskReceipt
// // for our to be submitted Task.
// const taskReceiptId = await gelatoCore.currentTaskReceiptId();
// const taskReceipt = new GelatoCoreLib.TaskReceipt({
// id: taskReceiptId,
// userProxy: dsa.address,
// provider: gelatoSelfProvider,
// tasks: [taskRebalanceDSRToCDAIifBetter],
// expiryDate,
// });
// ======= 📣 TASK EXECUTION 📣 =========
// This stuff is normally automated by the Gelato Network and Dapp Developers
// and their Users don't have to take care of it. However, for local testing
// we simulate the Gelato Execution logic.
// // ======= 📣 TASK EXECUTION 📣 =========
// // This stuff is normally automated by the Gelato Network and Dapp Developers
// // and their Users don't have to take care of it. However, for local testing
// // we simulate the Gelato Execution logic.
// First we fetch the gelatoGasPrice as fed by ChainLink oracle. Gelato
// allows Users to specify a maximum fast gwei gas price for their Tasks
// to remain executable up until.
const gelatoGasPrice = await hre.run("fetchGelatoGasPrice");
expect(gelatoGasPrice).to.be.lte(
taskRebalanceDSRToCDAIifBetter.selfProviderGasPriceCeil
);
// // First we fetch the gelatoGasPrice as fed by ChainLink oracle. Gelato
// // allows Users to specify a maximum fast gwei gas price for their Tasks
// // to remain executable up until.
// const gelatoGasPrice = await hre.run("fetchGelatoGasPrice");
// expect(gelatoGasPrice).to.be.lte(
// taskRebalanceDSRToCDAIifBetter.selfProviderGasPriceCeil
// );
// Let's first check if our Task is executable. Since both MockDSR and MockCDAI
// are deployed with a normalized per second rate of APY_2_PERCENT_IN_SECONDS
// (1000000000627937192491029810 in 10**27 precision) in both of them, we
// expect ConditionNotOk because ANotGreaterOrEqualToBbyMinspread.
// Check out contracts/ConditionCompareUintsFromTwoSources.sol to see how
// how the comparison of MockDSR and MockCDAI is implemented in Condition code.
expect(
await gelatoCore.canExec(
taskReceipt,
taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
gelatoGasPrice
)
).to.be.equal("ConditionNotOk:ANotGreaterOrEqualToBbyMinspread");
// // Let's first check if our Task is executable. Since both MockDSR and MockCDAI
// // are deployed with a normalized per second rate of APY_2_PERCENT_IN_SECONDS
// // (1000000000627937192491029810 in 10**27 precision) in both of them, we
// // expect ConditionNotOk because ANotGreaterOrEqualToBbyMinspread.
// // Check out contracts/ConditionCompareUintsFromTwoSources.sol to see how
// // how the comparison of MockDSR and MockCDAI is implemented in Condition code.
// expect(
// await gelatoCore.canExec(
// taskReceipt,
// taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
// gelatoGasPrice
// )
// ).to.be.equal("ConditionNotOk:ANotGreaterOrEqualToBbyMinspread");
// We defined a MIN_SPREAD of 10000000 points in the per second rate
// for our ConditionCompareUintsFromTwoSources. So we now
// set the CDAI.supplyRatePerSecond to be 10000000 higher than MockDSR.dsr
// and expect it to mean that our Task becomes executable.
await mockCDAI.setSupplyRatePerSecond(
(await mockDSR.dsr()).add(MIN_SPREAD)
);
expect(
await gelatoCore.canExec(
taskReceipt,
taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
gelatoGasPrice
)
).to.be.equal("OK");
// // We defined a MIN_SPREAD of 10000000 points in the per second rate
// // for our ConditionCompareUintsFromTwoSources. So we now
// // set the CDAI.supplyRatePerSecond to be 10000000 higher than MockDSR.dsr
// // and expect it to mean that our Task becomes executable.
// await mockCDAI.setSupplyRatePerSecond(
// (await mockDSR.dsr()).add(MIN_SPREAD)
// );
// expect(
// await gelatoCore.canExec(
// taskReceipt,
// taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
// gelatoGasPrice
// )
// ).to.be.equal("OK");
// To verify whether the execution of DSR=>CDAI has been successful in this Testing
// we look at changes in the CDAI balance of the DSA
const cDAI = await ethers.getContractAt(
IERC20.abi,
hre.network.config.CDAI
);
const dsaCDAIBefore = await cDAI.balanceOf(dsa.address);
// // To verify whether the execution of DSR=>CDAI has been successful in this Testing
// // we look at changes in the CDAI balance of the DSA
// const cDAI = await ethers.getContractAt(
// IERC20.abi,
// hre.network.config.CDAI
// );
// const dsaCDAIBefore = await cDAI.balanceOf(dsa.address);
// For testing we now simulate automatic Task Execution ❗
await expect(
gelatoCore.exec(taskReceipt, {
gasPrice: gelatoGasPrice, // Exectutor must use gelatoGasPrice (Chainlink fast gwei)
gasLimit: taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
})
).to.emit(gelatoCore, "LogExecSuccess");
// // For testing we now simulate automatic Task Execution ❗
// await expect(
// gelatoCore.exec(taskReceipt, {
// gasPrice: gelatoGasPrice, // Exectutor must use gelatoGasPrice (Chainlink fast gwei)
// gasLimit: taskRebalanceDSRToCDAIifBetter.selfProviderGasLimit,
// })
// ).to.emit(gelatoCore, "LogExecSuccess");
// Since the Execution was successful, we now expect our DSA to hold more
// CDAI then before. This concludes our testing.
expect(await cDAI.balanceOf(dsa.address)).to.be.gt(dsaCDAIBefore);
});
});
// // Since the Execution was successful, we now expect our DSA to hold more
// // CDAI then before. This concludes our testing.
// expect(await cDAI.balanceOf(dsa.address)).to.be.gt(dsaCDAIBefore);
// });
// });