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 enable(address) external;
|
||||||
function disable(address) external;
|
function disable(address) external;
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
||||||
*/
|
*/
|
||||||
MemoryInterface constant internal instaMemory = MemoryInterface(0xc109f7Ef06152c3a63dc7254fD861E612d3Ac571);
|
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.
|
* @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 enable(address) external;
|
||||||
function disable(address) external;
|
function disable(address) external;
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface } from "./interfaces.sol";
|
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
||||||
*/
|
*/
|
||||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x3254Ce8f5b1c82431B8f21Df01918342215825C2);
|
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.
|
* @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 disable(address) external;
|
||||||
|
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface } from "./interfaces.sol";
|
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,16 @@ abstract contract Stores {
|
||||||
MemoryInterface internal constant instaMemory =
|
MemoryInterface internal constant instaMemory =
|
||||||
MemoryInterface(0x56439117379A53bE3CC2C55217251e2481B7a1C8);
|
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.
|
* @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 enable(address) external;
|
||||||
function disable(address) external;
|
function disable(address) external;
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
|
@ -26,6 +26,16 @@ abstract contract Stores {
|
||||||
*/
|
*/
|
||||||
InstaMapping constant internal instaMapping = InstaMapping(0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88);
|
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.
|
* @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 enable(address) external;
|
||||||
function disable(address) external;
|
function disable(address) external;
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface } from "./interfaces.sol";
|
import { MemoryInterface, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
|
|
||||||
|
@ -20,6 +20,16 @@ abstract contract Stores {
|
||||||
*/
|
*/
|
||||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x3254Ce8f5b1c82431B8f21Df01918342215825C2);
|
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.
|
* @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 enable(address) external;
|
||||||
function disable(address) external;
|
function disable(address) external;
|
||||||
function isAuth(address) external view returns (bool);
|
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 {
|
interface InstaConnectors {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//SPDX-License-Identifier: MIT
|
//SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.7.0;
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
import { MemoryInterface, InstaMapping, ListInterface, InstaConnectors } from "./interfaces.sol";
|
||||||
|
|
||||||
|
|
||||||
abstract contract Stores {
|
abstract contract Stores {
|
||||||
|
@ -21,6 +21,16 @@ abstract contract Stores {
|
||||||
*/
|
*/
|
||||||
MemoryInterface constant internal instaMemory = MemoryInterface(0x6C7256cf7C003dD85683339F75DdE9971f98f2FD);
|
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.
|
* @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