mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Merge pull request #235 from Instadapp/spell-connector
DSA-Spell connector
This commit is contained in:
commit
1e78276bb2
|
@ -26,6 +26,15 @@ interface AccountInterface {
|
|||
function enable(address) external;
|
||||
function disable(address) external;
|
||||
function isAuth(address) external view returns (bool);
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
||||
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
|
||||
abstract contract Stores {
|
||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
|||
*/
|
||||
MemoryInterface constant internal instaMemory = MemoryInterface(0xc109f7Ef06152c3a63dc7254fD861E612d3Ac571);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x3565F6057b7fFE36984779A507fC87b31EFb0f09);
|
||||
|
||||
/**
|
||||
* @dev Return connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x67fCE99Dd6d8d659eea2a1ac1b8881c57eb6592B);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/arbitrum/connectors/dsa-spell/events.sol
Normal file
17
contracts/arbitrum/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/arbitrum/connectors/dsa-spell/main.sol
Normal file
91
contracts/arbitrum/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpellArbitrum is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
|
@ -21,6 +21,15 @@ interface AccountInterface {
|
|||
function enable(address) external;
|
||||
function disable(address) external;
|
||||
function isAuth(address) external view returns (bool);
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface } from "./interfaces.sol";
|
||||
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
|
||||
abstract contract Stores {
|
||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
|||
*/
|
||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x3254Ce8f5b1c82431B8f21Df01918342215825C2);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x9926955e0Dd681Dc303370C52f4Ad0a4dd061687);
|
||||
|
||||
/**
|
||||
* @dev Return connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/avalanche/connectors/dsa-spell/events.sol
Normal file
17
contracts/avalanche/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/avalanche/connectors/dsa-spell/main.sol
Normal file
91
contracts/avalanche/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpellAvalanche is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
|
@ -34,6 +34,16 @@ interface AccountInterface {
|
|||
function disable(address) external;
|
||||
|
||||
function isAuth(address) external view returns (bool);
|
||||
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface } from "./interfaces.sol";
|
||||
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
abstract contract Stores {
|
||||
/**
|
||||
|
@ -22,6 +22,16 @@ abstract contract Stores {
|
|||
MemoryInterface internal constant instaMemory =
|
||||
MemoryInterface(0x56439117379A53bE3CC2C55217251e2481B7a1C8);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x10e166c3FAF887D8a61dE6c25039231eE694E926);
|
||||
|
||||
/**
|
||||
* @dev Return connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x819910794a030403F69247E1e5C0bBfF1593B968);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/fantom/connectors/dsa-spell/events.sol
Normal file
17
contracts/fantom/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/fantom/connectors/dsa-spell/main.sol
Normal file
91
contracts/fantom/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpellFantom is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
|
@ -27,6 +27,15 @@ interface AccountInterface {
|
|||
function enable(address) external;
|
||||
function disable(address) external;
|
||||
function isAuth(address) external view returns (bool);
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
||||
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
|
||||
abstract contract Stores {
|
||||
|
@ -26,6 +26,16 @@ abstract contract Stores {
|
|||
*/
|
||||
InstaMapping constant internal instaMapping = InstaMapping(0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList Address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb);
|
||||
|
||||
/**
|
||||
* @dev Return connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/mainnet/connectors/dsa-spell/events.sol
Normal file
17
contracts/mainnet/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/mainnet/connectors/dsa-spell/main.sol
Normal file
91
contracts/mainnet/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpell is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
|
@ -23,6 +23,15 @@ interface AccountInterface {
|
|||
function enable(address) external;
|
||||
function disable(address) external;
|
||||
function isAuth(address) external view returns (bool);
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface } from "./interfaces.sol";
|
||||
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
abstract contract Stores {
|
||||
|
||||
|
@ -20,6 +20,16 @@ abstract contract Stores {
|
|||
*/
|
||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x3254Ce8f5b1c82431B8f21Df01918342215825C2);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x9926955e0Dd681Dc303370C52f4Ad0a4dd061687);
|
||||
|
||||
/**
|
||||
* @dev Returns connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/optimism/connectors/dsa-spell/events.sol
Normal file
17
contracts/optimism/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/optimism/connectors/dsa-spell/main.sol
Normal file
91
contracts/optimism/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpellOptimism is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
|
@ -26,6 +26,15 @@ interface AccountInterface {
|
|||
function enable(address) external;
|
||||
function disable(address) external;
|
||||
function isAuth(address) external view returns (bool);
|
||||
function cast(
|
||||
string[] calldata _targetNames,
|
||||
bytes[] calldata _datas,
|
||||
address _origin
|
||||
) external payable returns (bytes32[] memory responses);
|
||||
}
|
||||
|
||||
interface ListInterface {
|
||||
function accountID(address) external returns (uint64);
|
||||
}
|
||||
|
||||
interface InstaConnectors {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
||||
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||
|
||||
|
||||
abstract contract Stores {
|
||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
|||
*/
|
||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x6C7256cf7C003dD85683339F75DdE9971f98f2FD);
|
||||
|
||||
/**
|
||||
* @dev Return InstaList address
|
||||
*/
|
||||
ListInterface internal constant instaList = ListInterface(0x839c2D3aDe63DF5b0b8F3E57D5e145057Ab41556);
|
||||
|
||||
/**
|
||||
* @dev Return connectors registry address
|
||||
*/
|
||||
InstaConnectors internal constant instaConnectors = InstaConnectors(0x2A00684bFAb9717C21271E0751BCcb7d2D763c88);
|
||||
|
||||
/**
|
||||
* @dev Get Uint value from InstaMemory Contract.
|
||||
*/
|
||||
|
|
17
contracts/polygon/connectors/dsa-spell/events.sol
Normal file
17
contracts/polygon/connectors/dsa-spell/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma abicoder v2;
|
||||
|
||||
contract Events {
|
||||
event LogCastOnDSA(
|
||||
address indexed targetDSA,
|
||||
string[] connectors,
|
||||
bytes[] datas
|
||||
);
|
||||
event LogCastAny(
|
||||
string[] connectors,
|
||||
string connectorName,
|
||||
string eventName,
|
||||
bytes eventParam
|
||||
);
|
||||
}
|
91
contracts/polygon/connectors/dsa-spell/main.sol
Normal file
91
contracts/polygon/connectors/dsa-spell/main.sol
Normal file
|
@ -0,0 +1,91 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title DSA Spell.
|
||||
* @dev Cast spells on DSA.
|
||||
*/
|
||||
|
||||
import { AccountInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract DSASpellsResolver is Events, Stores {
|
||||
/**
|
||||
*@dev Casts spells on a DSA, caller DSA should be an auth of the target DSA. Reverts if any spell failed.
|
||||
*@notice Interact with a target DSA by casting spells on it.
|
||||
*@param targetDSA target DSA to cast spells on.
|
||||
*@param connectors Array of connector names (For example, ["1INCH-A", "BASIC-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castOnDSA(
|
||||
address targetDSA,
|
||||
string[] memory connectors,
|
||||
bytes[] memory datas
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(instaList.accountID(targetDSA) != 0, "not-a-DSA");
|
||||
|
||||
AccountInterface(targetDSA).cast(connectors, datas, address(this));
|
||||
|
||||
_eventName = "LogCastOnDSA(address,string[],bytes[])";
|
||||
_eventParam = abi.encode(targetDSA, connectors, datas);
|
||||
}
|
||||
|
||||
/**
|
||||
*@dev Casts spell on caller DSA. Stops casting further spells as soon as a spell gets casted successfully.
|
||||
* Reverts if none of the spells is successful.
|
||||
*@notice Casts the first successful spell on the DSA.
|
||||
*@param connectors Array of connector names, in preference order, if any (For example, ["1INCH-A", "ZEROX-A"]).
|
||||
*@param datas Array of connector calldatas (function selectors encoded with parameters).
|
||||
*/
|
||||
function castAny(string[] memory connectors, bytes[] memory datas)
|
||||
external
|
||||
payable
|
||||
returns (string memory eventName, bytes memory eventParam)
|
||||
{
|
||||
uint256 _length = connectors.length;
|
||||
require(_length > 0, "zero-length-not-allowed");
|
||||
require(datas.length == _length, "calldata-length-invalid");
|
||||
|
||||
(bool isOk, address[] memory _connectors) = instaConnectors
|
||||
.isConnectors(connectors);
|
||||
require(isOk, "connector-names-invalid");
|
||||
|
||||
string memory _connectorName;
|
||||
string memory _eventName;
|
||||
bytes memory _eventParam;
|
||||
bytes memory returnData;
|
||||
bool success;
|
||||
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
(success, returnData) = _connectors[i].delegatecall(datas[i]);
|
||||
|
||||
if (success) {
|
||||
_connectorName = connectors[i];
|
||||
(_eventName, _eventParam) = abi.decode(
|
||||
returnData,
|
||||
(string, bytes)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(success, "dsa-spells-failed");
|
||||
|
||||
eventName = "LogCastAny(string[],string,string,bytes)";
|
||||
eventParam = abi.encode(
|
||||
connectors,
|
||||
_connectorName,
|
||||
_eventName,
|
||||
_eventParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2DSASpellPolygon is DSASpellsResolver {
|
||||
string public name = "DSA-Spell-v1.0";
|
||||
}
|
180
test/arbitrum/dsa-spell/dsa-spell.test.ts
Normal file
180
test/arbitrum/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,180 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/arbitrum/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpellArbitrum__factory } from "../../../typechain";
|
||||
import { Signer, Contract } from "ethers";
|
||||
import { BigNumber } from "bignumber.js";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpellArbitrum__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let USDC = "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aETH = "0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8";
|
||||
let aEth = new ethers.Contract(aETH, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A", "AAVE-V3-A", "AAVE-V3-A"];
|
||||
let methods = ["withdraw", "deposit", "borrow"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
[ETH, ethers.constants.MaxUint256, 0, 0],
|
||||
[USDC, ethers.utils.parseUnits("1", 6), 2, 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(0);
|
||||
expect(await usdc.connect(wallet0).balanceOf(dsaWallet1.address)).to.be.gte(
|
||||
new BigNumber(1).multipliedBy(1e6).toString()
|
||||
);
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V3-A"];
|
||||
let methods = ["deposit"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aEth.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
185
test/avalanche/dsa-spell/dsa-spell.test.ts
Normal file
185
test/avalanche/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,185 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/avalanche/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpellAvalanche__factory } from "../../../typechain";
|
||||
import er20abi from "../../../scripts/constant/abi/basics/erc20.json";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let walletBsigner: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpellAvalanche__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
dsaWallet2 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet2.address).to.be.true;
|
||||
});
|
||||
|
||||
it("Deposit avax into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit avax into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let AVAX = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let USDC = "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aAVAX = "0x6d80113e533a2C0fe82EaBD35f1875DcEA89Ea97";
|
||||
let aAvax = new ethers.Contract(aAVAX, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A", "AAVE-V3-A", "AAVE-V3-A"];
|
||||
let methods = ["withdraw", "deposit", "borrow"];
|
||||
let params = [
|
||||
[AVAX, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
[AVAX, ethers.constants.MaxUint256, 0, 0],
|
||||
[USDC, ethers.utils.parseUnits("1", 6), 2, 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(0);
|
||||
expect(await usdc.connect(wallet0).balanceOf(dsaWallet1.address)).to.be.gte(
|
||||
new BigNumber(1).multipliedBy(1e6).toString()
|
||||
);
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V3-A", "AAVE-V2-A"];
|
||||
let methods = ["deposit","deposit"];
|
||||
let params = [
|
||||
[AVAX, ethers.utils.parseEther("10"), 0, 0],
|
||||
[AVAX, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aAvax.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
182
test/fantom/dsa-spell/dsa-spell.test.ts
Normal file
182
test/fantom/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,182 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/fantom/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpellFantom__factory } from "../../../typechain";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpellFantom__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
dsaWallet2 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet2.address).to.be.true;
|
||||
});
|
||||
|
||||
it("Deposit ftm into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit ftm into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let FTM = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let aFTM = "0x6d80113e533a2C0fe82EaBD35f1875DcEA89Ea97";
|
||||
let USDC = "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aFtm = new ethers.Contract(aFTM, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A", "AAVE-V3-A", "AAVE-V3-A"];
|
||||
let methods = ["withdraw", "deposit", "borrow"];
|
||||
let params = [
|
||||
[FTM, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
[FTM, ethers.constants.MaxUint256, 0, 0],
|
||||
[USDC, ethers.utils.parseUnits("1", 5), 2, 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(0);
|
||||
expect(await usdc.connect(wallet0).balanceOf(dsaWallet1.address)).to.be.gte(
|
||||
new BigNumber(1).multipliedBy(1e5).toString()
|
||||
);
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V3-A"];
|
||||
let methods = ["deposit"];
|
||||
let params = [
|
||||
[FTM, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aFtm.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
176
test/mainnet/dsa-spell/dsa-spell.test.ts
Normal file
176
test/mainnet/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/mainnet/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpell__factory } from "../../../typechain";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpell__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aETH = "0x030bA81f1c18d280636F32af80b9AAd02Cf0854e";
|
||||
let aEth = new ethers.Contract(aETH, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A"];
|
||||
let methods = ["withdraw"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(new BigNumber(8).multipliedBy(1e18).toString());
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V2-A", "AAVE-V1-A"];
|
||||
let methods = ["deposit", "deposit"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("10"), 0, 0],
|
||||
[ETH, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aEth.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
180
test/optimism/dsa-spell/dsa-spell.test.ts
Normal file
180
test/optimism/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,180 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/optimism/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpellOptimism__factory } from "../../../typechain";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpellOptimism__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit eth into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let USDC = "0x7F5c764cBc14f9669B88837ca1490cCa17c31607";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aETH = "0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8";
|
||||
let aEth = new ethers.Contract(aETH, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A", "AAVE-V3-A", "AAVE-V3-A"];
|
||||
let methods = ["withdraw", "deposit", "borrow"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
[ETH, ethers.constants.MaxUint256, 0, 0],
|
||||
[USDC, ethers.utils.parseUnits("1", 6), 2, 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(0);
|
||||
expect(await usdc.connect(wallet0).balanceOf(dsaWallet1.address)).to.be.gte(
|
||||
new BigNumber(1).multipliedBy(1e6).toString()
|
||||
);
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V3-A"];
|
||||
let methods = ["deposit"];
|
||||
let params = [
|
||||
[ETH, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aEth.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
185
test/polygon/dsa-spell/dsa-spell.test.ts
Normal file
185
test/polygon/dsa-spell/dsa-spell.test.ts
Normal file
|
@ -0,0 +1,185 @@
|
|||
import hre from "hardhat";
|
||||
import axios from "axios";
|
||||
import { expect } from "chai";
|
||||
const { ethers } = hre; //check
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addresses } from "../../../scripts/tests/polygon/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2DSASpellPolygon__factory } from "../../../typechain";
|
||||
import er20abi from "../../../scripts/constant/abi/basics/erc20.json";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
|
||||
describe("DSA Spell", function () {
|
||||
const connectorName = "dsa-spell-test";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let dsaWallet1: any;
|
||||
let dsaWallet2: any;
|
||||
let walletB: any;
|
||||
let wallet0: any;
|
||||
let walletBsigner: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: any;
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
[wallet0] = await ethers.getSigners();
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2DSASpellPolygon__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("\tConnector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
walletB = await ethers.getSigner(dsaWallet0.address);
|
||||
dsaWallet1 = await buildDSAv2(dsaWallet0.address);
|
||||
expect(!!dsaWallet1.address).to.be.true;
|
||||
console.log(`\t${dsaWallet1.address}`);
|
||||
dsaWallet2 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet2.address).to.be.true;
|
||||
});
|
||||
|
||||
it("Deposit matic into DSA wallet 0", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
|
||||
it("Deposit matic into DSA wallet 1", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet1.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
let MATIC = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
let USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
|
||||
let aMATIC = "0x6d80113e533a2C0fe82EaBD35f1875DcEA89Ea97";
|
||||
let usdc = new ethers.Contract(USDC, abis.basic.erc20);
|
||||
let aMatic = new ethers.Contract(aMATIC, abis.basic.aToken);
|
||||
var abi = [
|
||||
"function withdraw(address,uint256,address,uint256,uint256)",
|
||||
"function deposit(address,uint256,uint256,uint256)",
|
||||
"function borrow(address,uint256,uint256,uint256,uint256)"
|
||||
];
|
||||
function getCallData(spell: string, params: any) {
|
||||
var iface = new ethers.utils.Interface(abi);
|
||||
let data = iface.encodeFunctionData(spell, params);
|
||||
return ethers.utils.hexlify(data);
|
||||
}
|
||||
|
||||
it("should cast spells", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [dsaWallet1.address, connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["BASIC-A", "AAVE-V3-A", "AAVE-V3-A"];
|
||||
let methods = ["withdraw", "deposit", "borrow"];
|
||||
let params = [
|
||||
[MATIC, ethers.utils.parseEther("2"), dsaWallet0.address, 0, 0],
|
||||
[MATIC, ethers.constants.MaxUint256, 0, 0],
|
||||
[USDC, ethers.utils.parseUnits("1", 6), 2, 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castOnDSA",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after cast on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet1.address)).to.be.lte(0);
|
||||
expect(await usdc.connect(wallet0).balanceOf(dsaWallet1.address)).to.be.gte(
|
||||
new BigNumber(1).multipliedBy(1e6).toString()
|
||||
);
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(12).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it("should cast spell on the first successful", async function () {
|
||||
async function getArg(connectors: any, spells: any, params: any) {
|
||||
let datas = [];
|
||||
for (let i = 0; i < connectors.length; i++) {
|
||||
datas.push(getCallData(spells[i], params[i]));
|
||||
}
|
||||
return [connectors, datas];
|
||||
}
|
||||
|
||||
let connectors = ["AAVE-V3-A", "AAVE-V2-A"];
|
||||
let methods = ["deposit","deposit"];
|
||||
let params = [
|
||||
[MATIC, ethers.utils.parseEther("10"), 0, 0],
|
||||
[MATIC, ethers.utils.parseEther("10"), 0, 0]
|
||||
];
|
||||
let arg = await getArg(connectors, methods, params);
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "castAny",
|
||||
args: arg
|
||||
}
|
||||
];
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), await wallet0.getAddress());
|
||||
const receipt = await tx.wait();
|
||||
});
|
||||
|
||||
it("should check balances after spells on DSA", async function () {
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
|
||||
new BigNumber(2).multipliedBy(1e18).toString()
|
||||
);
|
||||
expect(await aMatic.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
|
||||
new BigNumber(10).multipliedBy(1e18).toString()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user