mirror of
https://github.com/Instadapp/dsa-polygon-migration.git
synced 2024-07-29 22:27:58 +00:00
Merge pull request #11 from Instadapp/flashloan-setup
Polygon flashloan
This commit is contained in:
commit
b261886eed
113
contracts/mock/aave-v2-migrator/main.sol
Normal file
113
contracts/mock/aave-v2-migrator/main.sol
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import { Variables } from "./variables.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title InstaAccountV2 Implementation-M2.
|
||||||
|
* @dev DeFi Smart Account Wallet for polygon migration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface ConnectorsInterface {
|
||||||
|
function isConnectors(string[] calldata connectorNames) external view returns (bool, address[] memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Constants is Variables {
|
||||||
|
// InstaIndex Address.
|
||||||
|
address internal constant instaIndex = 0xA9B99766E6C676Cf1975c0D3166F96C0848fF5ad;
|
||||||
|
// Migration contract Address.
|
||||||
|
address internal constant migrationContract = 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9;
|
||||||
|
// Connnectors Address.
|
||||||
|
address public constant connectorsM1 = 0x0a0a82D2F86b9E46AE60E22FCE4e8b916F858Ddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract InstaImplementationM2 is Constants {
|
||||||
|
|
||||||
|
function decodeEvent(bytes memory response) internal pure returns (string memory _eventCode, bytes memory _eventParams) {
|
||||||
|
if (response.length > 0) {
|
||||||
|
(_eventCode, _eventParams) = abi.decode(response, (string, bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event LogCastMigrate(
|
||||||
|
address indexed origin,
|
||||||
|
address indexed sender,
|
||||||
|
uint256 value,
|
||||||
|
string[] targetsNames,
|
||||||
|
address[] targets,
|
||||||
|
string[] eventNames,
|
||||||
|
bytes[] eventParams
|
||||||
|
);
|
||||||
|
|
||||||
|
receive() external payable {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Delegate the calls to Connector.
|
||||||
|
* @param _target Connector address
|
||||||
|
* @param _data CallData of function.
|
||||||
|
*/
|
||||||
|
function spell(address _target, bytes memory _data) internal returns (bytes memory response) {
|
||||||
|
require(_target != address(0), "target-invalid");
|
||||||
|
assembly {
|
||||||
|
let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0)
|
||||||
|
let size := returndatasize()
|
||||||
|
|
||||||
|
response := mload(0x40)
|
||||||
|
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||||
|
mstore(response, size)
|
||||||
|
returndatacopy(add(response, 0x20), 0, size)
|
||||||
|
|
||||||
|
switch iszero(succeeded)
|
||||||
|
case 1 {
|
||||||
|
// throw if delegatecall failed
|
||||||
|
returndatacopy(0x00, 0x00, size)
|
||||||
|
revert(0x00, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev This is the main function, Where all the different functions are called
|
||||||
|
* from Smart Account.
|
||||||
|
* @param _targetNames Array of Connector address.
|
||||||
|
* @param _datas Array of Calldata.
|
||||||
|
*/
|
||||||
|
function castMigrate(
|
||||||
|
string[] calldata _targetNames,
|
||||||
|
bytes[] calldata _datas,
|
||||||
|
address _origin
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (bytes32) // Dummy return to fix instaIndex buildWithCast function
|
||||||
|
{
|
||||||
|
uint256 _length = _targetNames.length;
|
||||||
|
require(msg.sender == migrationContract, "2: permission-denied");
|
||||||
|
require(_length != 0, "2: length-invalid");
|
||||||
|
require(_length == _datas.length , "2: array-length-invalid");
|
||||||
|
|
||||||
|
string[] memory eventNames = new string[](_length);
|
||||||
|
bytes[] memory eventParams = new bytes[](_length);
|
||||||
|
|
||||||
|
// TODO: restrict migration contract to run something specific? or give is all access as it doesn't have power to run anything else
|
||||||
|
(bool isOk, address[] memory _targets) = ConnectorsInterface(connectorsM1).isConnectors(_targetNames);
|
||||||
|
|
||||||
|
require(isOk, "2: not-connector");
|
||||||
|
|
||||||
|
for (uint i = 0; i < _length; i++) {
|
||||||
|
bytes memory response = spell(_targets[i], _datas[i]);
|
||||||
|
(eventNames[i], eventParams[i]) = decodeEvent(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit LogCastMigrate(
|
||||||
|
_origin,
|
||||||
|
msg.sender,
|
||||||
|
msg.value,
|
||||||
|
_targetNames,
|
||||||
|
_targets,
|
||||||
|
eventNames,
|
||||||
|
eventParams
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
contracts/mock/aave-v2-migrator/variables.sol
Normal file
6
contracts/mock/aave-v2-migrator/variables.sol
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
contract Variables {
|
||||||
|
// Auth Module(Address of Auth => bool).
|
||||||
|
mapping (address => bool) internal _auth;
|
||||||
|
}
|
|
@ -27,4 +27,12 @@ contract Events {
|
||||||
);
|
);
|
||||||
|
|
||||||
event LogMigrate(uint _id);
|
event LogMigrate(uint _id);
|
||||||
|
|
||||||
|
event LogFlashLoan(
|
||||||
|
address indexed sender,
|
||||||
|
address[] tokens,
|
||||||
|
uint[] amounts,
|
||||||
|
uint[] feeAmts,
|
||||||
|
uint route
|
||||||
|
);
|
||||||
}
|
}
|
|
@ -25,6 +25,15 @@ struct AaveData {
|
||||||
address[] borrowTokens;
|
address[] borrowTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CastData {
|
||||||
|
address dsa;
|
||||||
|
uint route;
|
||||||
|
address[] tokens;
|
||||||
|
uint[] amounts;
|
||||||
|
string[] dsaTargets;
|
||||||
|
bytes[] dsaData;
|
||||||
|
}
|
||||||
|
|
||||||
interface IndexInterface {
|
interface IndexInterface {
|
||||||
function master() external view returns (address);
|
function master() external view returns (address);
|
||||||
}
|
}
|
||||||
|
@ -99,5 +108,9 @@ interface AaveInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InstaListInterface {
|
interface InstaListInterface {
|
||||||
function accountID(address) external view returns (uint);
|
function accountID(address) external view returns (uint64);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DSAInterface {
|
||||||
|
function castMigrate(string[] calldata _targets, bytes[] calldata _datas, address _origin) external payable returns (bytes32);
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2;
|
||||||
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import { TokenInterface } from "../../common/interfaces.sol";
|
import { TokenInterface } from "../../common/interfaces.sol";
|
||||||
import { AccountInterface, AaveData, AaveInterface, IndexInterface } from "./interfaces.sol";
|
import { AccountInterface, AaveData, AaveInterface, IndexInterface, CastData, DSAInterface } from "./interfaces.sol";
|
||||||
import { Events } from "./events.sol";
|
import { Events } from "./events.sol";
|
||||||
import { Helpers } from "./helpers.sol";
|
import { Helpers } from "./helpers.sol";
|
||||||
|
|
||||||
|
@ -126,7 +126,58 @@ contract AaveV2Migrator is MigrateResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract InstaAaveV2MigratorReceiverImplementation is AaveV2Migrator {
|
contract InstaFlash is AaveV2Migrator {
|
||||||
|
|
||||||
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FOR SECURITY PURPOSE
|
||||||
|
* only Smart DEFI Account can access the liquidity pool contract
|
||||||
|
*/
|
||||||
|
modifier isDSA {
|
||||||
|
uint64 id = instaList.accountID(msg.sender);
|
||||||
|
require(id != 0, "not-dsa-id");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initiateFlashLoan(
|
||||||
|
address[] calldata _tokens,
|
||||||
|
uint256[] calldata _amounts,
|
||||||
|
uint /*_route */, // no use of route but just to follow current flashloan pattern
|
||||||
|
bytes calldata data
|
||||||
|
) external isDSA {
|
||||||
|
uint _length = _tokens.length;
|
||||||
|
require(_length == _amounts.length, "not-equal-length");
|
||||||
|
uint[] memory iniBal = new uint[](_length);
|
||||||
|
IERC20[] memory _tokenContracts = new IERC20[](_length);
|
||||||
|
for (uint i = 0; i < _length; i++) {
|
||||||
|
_tokenContracts[i] = IERC20(_tokens[i]);
|
||||||
|
iniBal[i] = _tokenContracts[i].balanceOf(address(this));
|
||||||
|
_tokenContracts[i].safeTransfer(msg.sender, _amounts[i]);
|
||||||
|
}
|
||||||
|
CastData memory cd;
|
||||||
|
(cd.dsa, cd.route, cd.tokens, cd.amounts, cd.dsaTargets, cd.dsaData) = abi.decode(
|
||||||
|
data,
|
||||||
|
(address, uint256, address[], uint256[], string[], bytes[])
|
||||||
|
);
|
||||||
|
DSAInterface(msg.sender).castMigrate(cd.dsaTargets, cd.dsaData, 0xB7fA44c2E964B6EB24893f7082Ecc08c8d0c0F87);
|
||||||
|
for (uint i = 0; i < _length; i++) {
|
||||||
|
uint _finBal = _tokenContracts[i].balanceOf(address(this));
|
||||||
|
require(_finBal >= iniBal[i], "flashloan-not-returned");
|
||||||
|
}
|
||||||
|
uint[] memory _feeAmts = new uint[](_length);
|
||||||
|
emit LogFlashLoan(
|
||||||
|
msg.sender,
|
||||||
|
_tokens,
|
||||||
|
_amounts,
|
||||||
|
_feeAmts,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
contract InstaAaveV2MigratorReceiverImplementation is InstaFlash {
|
||||||
function migrate(uint _id) external {
|
function migrate(uint _id) external {
|
||||||
bytes memory _data = positions[_id];
|
bytes memory _data = positions[_id];
|
||||||
|
|
||||||
|
|
10
contracts/receivers/flashloan-connector/events.sol
Normal file
10
contracts/receivers/flashloan-connector/events.sol
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
pragma solidity >=0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
contract Events {
|
||||||
|
event LogFlashBorrow(address token, uint256 tokenAmt);
|
||||||
|
event LogFlashPayback(address token, uint256 tokenAmt);
|
||||||
|
|
||||||
|
event LogFlashMultiBorrow(address[] token, uint256[] tokenAmts);
|
||||||
|
event LogFlashMultiPayback(address[] token, uint256[] tokenAmts);
|
||||||
|
}
|
6
contracts/receivers/flashloan-connector/interfaces.sol
Normal file
6
contracts/receivers/flashloan-connector/interfaces.sol
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pragma solidity >=0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
interface InstaFlashV2Interface {
|
||||||
|
function initiateFlashLoan(address[] calldata tokens, uint256[] calldata amts, uint route, bytes calldata data) external;
|
||||||
|
}
|
118
contracts/receivers/flashloan-connector/main.sol
Normal file
118
contracts/receivers/flashloan-connector/main.sol
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
import { TokenInterface } from "../../common/interfaces.sol";
|
||||||
|
import { DSMath } from "../../common/math.sol";
|
||||||
|
import { Stores } from "../../common/stores-polygon.sol";
|
||||||
|
import { Variables } from "./variables.sol";
|
||||||
|
import { Events } from "./events.sol";
|
||||||
|
|
||||||
|
contract LiquidityResolver is DSMath, Stores, Variables, Events {
|
||||||
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Borrow Flashloan and Cast spells.
|
||||||
|
* @param token Token Address.
|
||||||
|
* @param amt Token Amount.
|
||||||
|
* @param data targets & data for cast.
|
||||||
|
*/
|
||||||
|
function flashBorrowAndCast(
|
||||||
|
address token,
|
||||||
|
uint amt,
|
||||||
|
uint route,
|
||||||
|
bytes memory data
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
address[] memory tokens = new address[](1);
|
||||||
|
uint[] memory amts = new uint[](1);
|
||||||
|
tokens[0] = token;
|
||||||
|
amts[0] = amt;
|
||||||
|
|
||||||
|
instaPool.initiateFlashLoan(tokens, amts, route, data);
|
||||||
|
|
||||||
|
_eventName = "LogFlashBorrow(address,uint256)";
|
||||||
|
_eventParam = abi.encode(token, amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Return token to InstaPool.
|
||||||
|
* @param token Token Address.
|
||||||
|
* @param amt Token Amount.
|
||||||
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
||||||
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
||||||
|
*/
|
||||||
|
function flashPayback(
|
||||||
|
address token,
|
||||||
|
uint amt,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
IERC20 tokenContract = IERC20(token);
|
||||||
|
|
||||||
|
tokenContract.safeTransfer(address(instaPool), _amt);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogFlashPayback(address,uint256)";
|
||||||
|
_eventParam = abi.encode(token, _amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Borrow Flashloan and Cast spells.
|
||||||
|
* @param tokens Array of token Addresses.
|
||||||
|
* @param amts Array of token Amounts.
|
||||||
|
* @param route Route to borrow.
|
||||||
|
* @param data targets & data for cast.
|
||||||
|
*/
|
||||||
|
function flashMultiBorrowAndCast(
|
||||||
|
address[] calldata tokens,
|
||||||
|
uint[] calldata amts,
|
||||||
|
uint route,
|
||||||
|
bytes calldata data
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
instaPool.initiateFlashLoan(tokens, amts, route, data);
|
||||||
|
|
||||||
|
_eventName = "LogFlashMultiBorrow(address[],uint256[])";
|
||||||
|
_eventParam = abi.encode(tokens, amts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Return Multiple token liquidity to InstaPool.
|
||||||
|
* @param tokens Array of token addresses.
|
||||||
|
* @param amts Array of token amounts.
|
||||||
|
* @param getId get token amounts at this IDs from `InstaMemory` Contract.
|
||||||
|
* @param setId set token amounts at this IDs in `InstaMemory` Contract.
|
||||||
|
*/
|
||||||
|
function flashMultiPayback(
|
||||||
|
address[] calldata tokens,
|
||||||
|
uint[] calldata amts,
|
||||||
|
uint[] calldata getId,
|
||||||
|
uint[] calldata setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _length = tokens.length;
|
||||||
|
|
||||||
|
uint[] memory _amts = new uint[](_length);
|
||||||
|
|
||||||
|
for (uint i = 0; i < _length; i++) {
|
||||||
|
uint _amt = getUint(getId[i], amts[i]);
|
||||||
|
|
||||||
|
_amts[i] = _amt;
|
||||||
|
|
||||||
|
IERC20 tokenContract = IERC20(tokens[i]);
|
||||||
|
|
||||||
|
tokenContract.safeTransfer(address(instaPool), _amt);
|
||||||
|
|
||||||
|
setUint(setId[i], _amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventName = "LogFlashMultiPayback(address[],uint256[])";
|
||||||
|
_eventParam = abi.encode(tokens, _amts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectInstaPool is LiquidityResolver {
|
||||||
|
string public name = "Instapool-v1";
|
||||||
|
}
|
12
contracts/receivers/flashloan-connector/variables.sol
Normal file
12
contracts/receivers/flashloan-connector/variables.sol
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import { InstaFlashV2Interface } from "./interfaces.sol";
|
||||||
|
|
||||||
|
contract Variables {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Instapool / Receiver contract proxy
|
||||||
|
*/
|
||||||
|
InstaFlashV2Interface public constant instaPool = InstaFlashV2Interface(0x4A090897f47993C2504144419751D6A91D79AbF4);
|
||||||
|
}
|
234
test/receiver_flashloan.test.js
Normal file
234
test/receiver_flashloan.test.js
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
const hre = require("hardhat");
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const { ethers, network, waffle } = hre;
|
||||||
|
const { provider, deployContract } = waffle
|
||||||
|
|
||||||
|
const Receiver = require("../artifacts/contracts/receivers/aave-v2-receiver/main.sol/InstaAaveV2MigratorReceiverImplementation.json")
|
||||||
|
const Implementation = require("../artifacts/contracts/mock/aave-v2-migrator/main.sol/InstaImplementationM2.json")
|
||||||
|
|
||||||
|
describe("Receiver", function() {
|
||||||
|
let accounts, account, receiver, master, implementation
|
||||||
|
|
||||||
|
const usdc = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
|
||||||
|
const usdt = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'
|
||||||
|
const dai = '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063'
|
||||||
|
const wbtc = '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6'
|
||||||
|
const weth = '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
|
||||||
|
const wmatic = '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270'
|
||||||
|
|
||||||
|
const instaImplementations = '0x39d3d5e7c11D61E072511485878dd84711c19d4A'
|
||||||
|
|
||||||
|
const maxValue = '115792089237316195423570985008687907853269984665640564039457584007913129639935'
|
||||||
|
|
||||||
|
const erc20Abi = [
|
||||||
|
"function balanceOf(address) view returns (uint)",
|
||||||
|
"function transfer(address to, uint amount)",
|
||||||
|
"function approve(address spender, uint amount)"
|
||||||
|
]
|
||||||
|
|
||||||
|
const instaImplementationABI = [
|
||||||
|
"function addImplementation(address _implementation, bytes4[] calldata _sigs)",
|
||||||
|
"function getImplementation(bytes4 _sig) view returns (address)",
|
||||||
|
"function removeImplementation(address _implementation)"
|
||||||
|
]
|
||||||
|
|
||||||
|
const implementations_m2Sigs = ["0x5a19a5eb"]
|
||||||
|
|
||||||
|
before(async function() {
|
||||||
|
accounts = await ethers.getSigners()
|
||||||
|
account = accounts[0]
|
||||||
|
|
||||||
|
masterAddress = "0x31de2088f38ed7F8a4231dE03973814edA1f8773"
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ masterAddress ]
|
||||||
|
})
|
||||||
|
|
||||||
|
master = ethers.provider.getSigner(masterAddress)
|
||||||
|
|
||||||
|
receiver = await deployContract(account, Receiver, [])
|
||||||
|
implementation = await deployContract(account, Implementation, [])
|
||||||
|
|
||||||
|
console.log("Receiver deployed: ", receiver.address)
|
||||||
|
console.log("ImplementationM2 deployed: ", implementation.address)
|
||||||
|
|
||||||
|
await master.sendTransaction({
|
||||||
|
to: receiver.address,
|
||||||
|
value: ethers.utils.parseEther("45400000")
|
||||||
|
})
|
||||||
|
|
||||||
|
const usdcHolderAddr = '0x986a2fCa9eDa0e06fBf7839B89BfC006eE2a23Dd' // 1,000,000
|
||||||
|
await account.sendTransaction({ to: usdcHolderAddr, value: ethers.utils.parseEther('1') })
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ usdcHolderAddr ]
|
||||||
|
})
|
||||||
|
const usdcHolder = ethers.provider.getSigner(usdcHolderAddr)
|
||||||
|
const usdcContract = new ethers.Contract(usdc, erc20Abi, usdcHolder)
|
||||||
|
await usdcContract.transfer(receiver.address, ethers.utils.parseUnits('1000000', 6))
|
||||||
|
|
||||||
|
const daiHolderAddr = '0x7A61A0Ed364E599Ae4748D1EbE74bf236Dd27B09' // 300,000
|
||||||
|
await accounts[0].sendTransaction({ to: daiHolderAddr, value: ethers.utils.parseEther('1') })
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ daiHolderAddr ]
|
||||||
|
})
|
||||||
|
const daiHolder = ethers.provider.getSigner(daiHolderAddr)
|
||||||
|
const daiContract = new ethers.Contract(dai, erc20Abi, daiHolder)
|
||||||
|
await daiContract.transfer(receiver.address, ethers.utils.parseUnits('10000', 18))
|
||||||
|
})
|
||||||
|
|
||||||
|
// it("should change the implementation", async function() {
|
||||||
|
// const funder = await deployContract(master, Funder, [])
|
||||||
|
// await master.sendTransaction({
|
||||||
|
// to: funder.address,
|
||||||
|
// value: ethers.utils.parseEther("10")
|
||||||
|
// })
|
||||||
|
|
||||||
|
// await funder.kill()
|
||||||
|
|
||||||
|
// const proxyAbi = [
|
||||||
|
// "function upgradeTo(address newImplementation)"
|
||||||
|
// ]
|
||||||
|
|
||||||
|
// const masterProxyAddr = '0x697860CeE594c577F18f71cAf3d8B68D913c7366'
|
||||||
|
// const masterProxySigner = ethers.provider.getSigner(masterProxyAddr)
|
||||||
|
|
||||||
|
// const receiverProxy = '0x4A090897f47993C2504144419751D6A91D79AbF4'
|
||||||
|
// const receiverProxyContract = new ethers.Contract(receiverProxy, proxyAbi, masterProxySigner)
|
||||||
|
|
||||||
|
// await receiverProxyContract.upgradeTo(receiver.address)
|
||||||
|
// })
|
||||||
|
|
||||||
|
it("should match matic receiver", async function() {
|
||||||
|
const maticReceiver = await receiver.maticReceiver()
|
||||||
|
|
||||||
|
expect(maticReceiver).to.be.equal('0x0000000000000000000000000000000000001001')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should set implementationsM2", async function() {
|
||||||
|
|
||||||
|
const instaImplementationsContract = new ethers.Contract(instaImplementations, instaImplementationABI, master)
|
||||||
|
await instaImplementationsContract.connect(master).removeImplementation('0xEAac5739eB532110431b14D01017506DBA8f7b07')
|
||||||
|
await instaImplementationsContract.connect(master).addImplementation(implementation.address, implementations_m2Sigs)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should not flashloan non-dsa address", async function() {
|
||||||
|
const eoaAddr = '0xA35f3FEFEcb5160327d1B6A210b60D1e1d7968e3'
|
||||||
|
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ eoaAddr ]
|
||||||
|
})
|
||||||
|
|
||||||
|
const eoaSigner = ethers.provider.getSigner(eoaAddr)
|
||||||
|
|
||||||
|
await expect(receiver.connect(eoaSigner).initiateFlashLoan(
|
||||||
|
[usdc],
|
||||||
|
[ethers.utils.parseUnits('1000', 6)],
|
||||||
|
0,
|
||||||
|
'0x'
|
||||||
|
)).to.be.revertedWith('not-dsa-id')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("single token flashloan", async function() {
|
||||||
|
const dsaAddr = '0x150Acc42e6751776c9E784EfF830cB4f35aE98f3'
|
||||||
|
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ dsaAddr ]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dsaSigner = ethers.provider.getSigner(dsaAddr)
|
||||||
|
|
||||||
|
const aave = new ethers.utils.Interface([
|
||||||
|
'function deposit(address,uint256,uint256,uint256)',
|
||||||
|
'function withdraw(address,uint256,uint256,uint256)'
|
||||||
|
])
|
||||||
|
|
||||||
|
const basic = new ethers.utils.Interface([
|
||||||
|
'function withdraw(address,uint256,address,uint256,uint256)'
|
||||||
|
])
|
||||||
|
|
||||||
|
const abiCoder = ethers.utils.defaultAbiCoder
|
||||||
|
|
||||||
|
const abiData = abiCoder.encode(
|
||||||
|
['address', 'uint256', 'address[]', 'uint256[]', 'string[]', 'bytes[]'],
|
||||||
|
[
|
||||||
|
dsaAddr,
|
||||||
|
0,
|
||||||
|
[usdc],
|
||||||
|
[ethers.utils.parseUnits('1000', 6)],
|
||||||
|
['AAVE-V2-A', 'AAVE-V2-A', 'BASIC-A'],
|
||||||
|
[
|
||||||
|
aave.encodeFunctionData('deposit', [usdc, ethers.utils.parseUnits('1000', 6), 0, 0]),
|
||||||
|
aave.encodeFunctionData('withdraw', [usdc, ethers.utils.parseUnits('1000', 6), 0, 0]),
|
||||||
|
basic.encodeFunctionData('withdraw', [usdc, ethers.utils.parseUnits('1000', 6), receiver.address, 0, 0])
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
// console.log('abiData', abiData)
|
||||||
|
|
||||||
|
const tx = await receiver.connect(dsaSigner).initiateFlashLoan(
|
||||||
|
[usdc],
|
||||||
|
[ethers.utils.parseUnits('1000', 6)],
|
||||||
|
0,
|
||||||
|
abiData
|
||||||
|
)
|
||||||
|
|
||||||
|
await tx.wait()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("multi token flashloan", async function() {
|
||||||
|
const dsaAddr = '0x150Acc42e6751776c9E784EfF830cB4f35aE98f3'
|
||||||
|
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ dsaAddr ]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dsaSigner = ethers.provider.getSigner(dsaAddr)
|
||||||
|
|
||||||
|
const aave = new ethers.utils.Interface([
|
||||||
|
'function deposit(address,uint256,uint256,uint256)',
|
||||||
|
'function withdraw(address,uint256,uint256,uint256)'
|
||||||
|
])
|
||||||
|
|
||||||
|
const basic = new ethers.utils.Interface([
|
||||||
|
'function withdraw(address,uint256,address,uint256,uint256)'
|
||||||
|
])
|
||||||
|
|
||||||
|
const abiCoder = ethers.utils.defaultAbiCoder
|
||||||
|
|
||||||
|
const abiData = abiCoder.encode(
|
||||||
|
['address', 'uint256', 'address[]', 'uint256[]', 'string[]', 'bytes[]'],
|
||||||
|
[
|
||||||
|
dsaAddr,
|
||||||
|
0,
|
||||||
|
[usdc, dai],
|
||||||
|
[ethers.utils.parseUnits('1000', 6), ethers.utils.parseEther('5000')],
|
||||||
|
['AAVE-V2-A', 'AAVE-V2-A', 'AAVE-V2-A', 'AAVE-V2-A', 'BASIC-A', 'BASIC-A'],
|
||||||
|
[
|
||||||
|
aave.encodeFunctionData('deposit', [usdc, ethers.utils.parseUnits('1000', 6), 0, 0]),
|
||||||
|
aave.encodeFunctionData('deposit', [dai, ethers.utils.parseEther('5000'), 0, 0]),
|
||||||
|
aave.encodeFunctionData('withdraw', [usdc, ethers.utils.parseUnits('1000', 6), 0, 0]),
|
||||||
|
aave.encodeFunctionData('withdraw', [dai, ethers.utils.parseEther('5000'), 0, 0]),
|
||||||
|
basic.encodeFunctionData('withdraw', [usdc, ethers.utils.parseUnits('1000', 6), receiver.address, 0, 0]),
|
||||||
|
basic.encodeFunctionData('withdraw', [dai, ethers.utils.parseEther('5000'), receiver.address, 0, 0])
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
// console.log('abiData', abiData)
|
||||||
|
|
||||||
|
const tx = await receiver.connect(dsaSigner).initiateFlashLoan(
|
||||||
|
[usdc, dai],
|
||||||
|
[ethers.utils.parseUnits('1000', 6), ethers.utils.parseEther('5000')],
|
||||||
|
0,
|
||||||
|
abiData
|
||||||
|
)
|
||||||
|
|
||||||
|
await tx.wait()
|
||||||
|
})
|
||||||
|
})
|
|
@ -5,7 +5,8 @@ const { provider, deployContract } = waffle
|
||||||
|
|
||||||
const Migrator = require("../artifacts/contracts/receivers/aave-v2-receiver/main.sol/InstaAaveV2MigratorReceiverImplementation.json")
|
const Migrator = require("../artifacts/contracts/receivers/aave-v2-receiver/main.sol/InstaAaveV2MigratorReceiverImplementation.json")
|
||||||
const TokenMappingContract = require("../artifacts/contracts/receivers/mapping/main.sol/InstaPolygonTokenMapping.json")
|
const TokenMappingContract = require("../artifacts/contracts/receivers/mapping/main.sol/InstaPolygonTokenMapping.json")
|
||||||
const Implementations_m2Contract = require("../artifacts/contracts/implementation/aave-v2-migrator/main.sol/InstaImplementationM1.json")
|
const Implementations_m2Contract = require("../artifacts/contracts/implementation/aave-v2-migrator/main.sol/InstaImplementationM2.json")
|
||||||
|
const Funder = require("../artifacts/contracts/mock/funder.sol/Funder.json");
|
||||||
|
|
||||||
const tokenMaps = {
|
const tokenMaps = {
|
||||||
// polygon address : main net address
|
// polygon address : main net address
|
||||||
|
@ -21,7 +22,7 @@ const tokenMaps = {
|
||||||
|
|
||||||
//
|
//
|
||||||
describe("Migrator", function() {
|
describe("Migrator", function() {
|
||||||
let accounts, masterAddress, master, migrator, ethereum, instapool, tokenMapping, implementations_m2Contract
|
let accounts, masterAddress, master, migrator, ethereum, instapool, tokenMapping, receiverSigner
|
||||||
|
|
||||||
const erc20Abi = [
|
const erc20Abi = [
|
||||||
"function balanceOf(address) view returns (uint)",
|
"function balanceOf(address) view returns (uint)",
|
||||||
|
@ -47,6 +48,8 @@ describe("Migrator", function() {
|
||||||
|
|
||||||
const instaConnectorsV2 = '0x0a0a82D2F86b9E46AE60E22FCE4e8b916F858Ddc'
|
const instaConnectorsV2 = '0x0a0a82D2F86b9E46AE60E22FCE4e8b916F858Ddc'
|
||||||
const instaImplementations = '0x39d3d5e7c11D61E072511485878dd84711c19d4A'
|
const instaImplementations = '0x39d3d5e7c11D61E072511485878dd84711c19d4A'
|
||||||
|
|
||||||
|
const receiverMsgSender = '0x0000000000000000000000000000000000001001'
|
||||||
|
|
||||||
|
|
||||||
const maxValue = '115792089237316195423570985008687907853269984665640564039457584007913129639935'
|
const maxValue = '115792089237316195423570985008687907853269984665640564039457584007913129639935'
|
||||||
|
@ -60,19 +63,26 @@ describe("Migrator", function() {
|
||||||
params: [ masterAddress ]
|
params: [ masterAddress ]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [ receiverMsgSender ]
|
||||||
|
})
|
||||||
|
|
||||||
accounts = await ethers.getSigners();
|
accounts = await ethers.getSigners();
|
||||||
master = ethers.provider.getSigner(masterAddress)
|
master = ethers.provider.getSigner(masterAddress)
|
||||||
|
|
||||||
|
receiverSigner = ethers.provider.getSigner(receiverMsgSender)
|
||||||
|
|
||||||
migrator = await deployContract(master, Migrator, [])
|
migrator = await deployContract(master, Migrator, [])
|
||||||
|
|
||||||
// instapool = await deployContract(master, InstaPool, [])
|
// instapool = await deployContract(master, InstaPool, [])
|
||||||
tokenMapping = await deployContract(master, TokenMappingContract, [Object.values(tokenMaps), Object.keys(tokenMaps)])
|
tokenMapping = await deployContract(master, TokenMappingContract, [Object.values(tokenMaps), Object.keys(tokenMaps)])
|
||||||
console.log("Migrator deployed: ", migrator.address)
|
console.log("Migrator deployed: ", migrator.address)
|
||||||
implementations_m2Contract = await deployContract(master, Implementations_m2Contract, [instaConnectorsV2, migrator.address])
|
// implementations_m2Contract = await deployContract(master, Implementations_m2Contract, [])
|
||||||
|
|
||||||
console.log("Migrator deployed: ", migrator.address)
|
console.log("Migrator deployed: ", migrator.address)
|
||||||
console.log("tokenMapping deployed: ", tokenMapping.address)
|
console.log("tokenMapping deployed: ", tokenMapping.address)
|
||||||
console.log("implementations_m2Contract deployed: ", implementations_m2Contract.address)
|
// console.log("implementations_m2Contract deployed: ", implementations_m2Contract.address)
|
||||||
|
|
||||||
await master.sendTransaction({
|
await master.sendTransaction({
|
||||||
to: migrator.address,
|
to: migrator.address,
|
||||||
|
@ -81,11 +91,11 @@ describe("Migrator", function() {
|
||||||
ethereum = network.provider
|
ethereum = network.provider
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should set implementationsV2", async function() {
|
// it("should set implementationsV2", async function() {
|
||||||
|
|
||||||
const instaImplementationsContract = new ethers.Contract(instaImplementations, instaImplementationABI, master)
|
// const instaImplementationsContract = new ethers.Contract(instaImplementations, instaImplementationABI, master)
|
||||||
await instaImplementationsContract.connect(master).addImplementation(implementations_m2Contract.address, implementations_m2Sigs)
|
// await instaImplementationsContract.connect(master).addImplementation(implementations_m2Contract.address, implementations_m2Sigs)
|
||||||
})
|
// })
|
||||||
|
|
||||||
it("should set tokens", async function() {
|
it("should set tokens", async function() {
|
||||||
const tx = await migrator.connect(master).addTokenSupport([...Object.keys(tokenMaps).slice(1, 3), "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"])
|
const tx = await migrator.connect(master).addTokenSupport([...Object.keys(tokenMaps).slice(1, 3), "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"])
|
||||||
|
@ -95,8 +105,17 @@ describe("Migrator", function() {
|
||||||
expect(isMatic).to.be.true;
|
expect(isMatic).to.be.true;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("fund receiver data setter", async function() {
|
||||||
|
const funder = await deployContract(master, Funder, [])
|
||||||
|
await master.sendTransaction({
|
||||||
|
to: funder.address,
|
||||||
|
value: ethers.utils.parseEther("1")
|
||||||
|
});
|
||||||
|
await funder.kill()
|
||||||
|
})
|
||||||
|
|
||||||
it("should set data", async function() {
|
it("should set data", async function() {
|
||||||
const tx = await migrator.onStateReceive("345", migrateData)
|
const tx = await migrator.connect(receiverSigner).onStateReceive("345", migrateData)
|
||||||
const receipt = await tx.wait()
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
const _migrateData = await migrator.positions("345")
|
const _migrateData = await migrator.positions("345")
|
||||||
|
@ -226,7 +245,7 @@ describe("Migrator", function() {
|
||||||
|
|
||||||
it("test migrate 2", async function() {
|
it("test migrate 2", async function() {
|
||||||
const positionData = '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000150acc42e6751776c9e784eff830cb4f35ae98f300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000056900d33ca7fc0000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000004a817c800000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000006b175474e89094c44da98b954eedeac495271d0f'
|
const positionData = '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000150acc42e6751776c9e784eff830cb4f35ae98f300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000056900d33ca7fc0000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000004a817c800000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000006b175474e89094c44da98b954eedeac495271d0f'
|
||||||
let tx = await migrator.onStateReceive("346", positionData)
|
let tx = await migrator.connect(receiverSigner).onStateReceive("346", positionData)
|
||||||
await tx.wait()
|
await tx.wait()
|
||||||
|
|
||||||
tx = await migrator.migrate("346")
|
tx = await migrator.migrate("346")
|
||||||
|
@ -242,7 +261,7 @@ describe("Migrator", function() {
|
||||||
|
|
||||||
it("test migrate 3", async function() {
|
it("test migrate 3", async function() {
|
||||||
const positionData = '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000032d99500f7621c6dc5391395d419236383dbff9700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000361a08405e8fd8000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000df847580000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7'
|
const positionData = '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000032d99500f7621c6dc5391395d419236383dbff9700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000361a08405e8fd8000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000df847580000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7'
|
||||||
let tx = await migrator.onStateReceive("347", positionData)
|
let tx = await migrator.connect(receiverSigner).onStateReceive("347", positionData)
|
||||||
await tx.wait()
|
await tx.wait()
|
||||||
|
|
||||||
tx = await migrator.migrate("347")
|
tx = await migrator.migrate("347")
|
||||||
|
@ -258,7 +277,7 @@ describe("Migrator", function() {
|
||||||
|
|
||||||
it("test migrate 4", async function() {
|
it("test migrate 4", async function() {
|
||||||
const positionData = '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000029601161ad5da8c54435f4065af3a0ee30cb24dd00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000b274d080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000574fbde60000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
|
const positionData = '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000029601161ad5da8c54435f4065af3a0ee30cb24dd00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000b274d080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000574fbde60000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
|
||||||
let tx = await migrator.onStateReceive("348", positionData)
|
let tx = await migrator.connect(receiverSigner).onStateReceive("348", positionData)
|
||||||
await tx.wait()
|
await tx.wait()
|
||||||
|
|
||||||
tx = await migrator.migrate("348")
|
tx = await migrator.migrate("348")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user