mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
commit
4548cad2cb
16
contracts/mainnet/connectors/lixir/events.sol
Normal file
16
contracts/mainnet/connectors/lixir/events.sol
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogDeposit(
|
||||
address indexed vault,
|
||||
uint256 shares,
|
||||
uint256 amount0In,
|
||||
uint256 amount1In
|
||||
);
|
||||
|
||||
event LogWithdraw(
|
||||
address indexed vault,
|
||||
uint256 amount0Out,
|
||||
uint256 amount1Out
|
||||
);
|
||||
}
|
||||
78
contracts/mainnet/connectors/lixir/helpers.sol
Normal file
78
contracts/mainnet/connectors/lixir/helpers.sol
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {
|
||||
function _deposit(
|
||||
address payable vaultAddress,
|
||||
uint256 amount0Desired,
|
||||
uint256 amount1Desired,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline
|
||||
) internal returns (
|
||||
uint256 shares,
|
||||
uint256 amount0In,
|
||||
uint256 amount1In
|
||||
) {
|
||||
uint256 shares;
|
||||
uint256 amount0In;
|
||||
uint256 amount1In;
|
||||
|
||||
if (msg.value > 0) {
|
||||
ILixirVaultETH vault = ILixirVaultETH(vaultAddress);
|
||||
|
||||
(
|
||||
shares,
|
||||
amount0In,
|
||||
amount1In
|
||||
) = vault.depositETH(
|
||||
uint8(vault.WETH_TOKEN()) == 1 ? amount0Desired : amount1Desired,
|
||||
uint8(vault.WETH_TOKEN()) == 1 ? amount0Min : amount1Min,
|
||||
uint8(vault.WETH_TOKEN()) == 1 ? amount1Min : amount0Min,
|
||||
recipient,
|
||||
deadline
|
||||
);
|
||||
} else {
|
||||
ILixirVault vault = ILixirVault(vaultAddress);
|
||||
(
|
||||
shares,
|
||||
amount0In,
|
||||
amount1In
|
||||
) = vault.deposit(
|
||||
amount0Desired,
|
||||
amount1Desired,
|
||||
amount0Min,
|
||||
amount1Min,
|
||||
recipient,
|
||||
deadline
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function _withdraw(
|
||||
address vaultAddress,
|
||||
uint256 shares,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline
|
||||
) internal returns (uint256 amount0Out, uint256 amount1Out) {
|
||||
ILixirVault vault = ILixirVault(vaultAddress);
|
||||
(
|
||||
amount0Out,
|
||||
amount1Out
|
||||
) = vault.withdraw(
|
||||
shares,
|
||||
amount0Min,
|
||||
amount1Min,
|
||||
recipient,
|
||||
deadline
|
||||
);
|
||||
}
|
||||
}
|
||||
204
contracts/mainnet/connectors/lixir/interface.sol
Normal file
204
contracts/mainnet/connectors/lixir/interface.sol
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
|
||||
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
||||
|
||||
interface IERC20Permit {
|
||||
/**
|
||||
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
|
||||
* given `owner`'s signed approval.
|
||||
*
|
||||
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
|
||||
* ordering also apply here.
|
||||
*
|
||||
* Emits an {Approval} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
* - `deadline` must be a timestamp in the future.
|
||||
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
|
||||
* over the EIP712-formatted function arguments.
|
||||
* - the signature must use ``owner``'s current nonce (see {nonces}).
|
||||
*
|
||||
* For more information on the signature format, see the
|
||||
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
|
||||
* section].
|
||||
*/
|
||||
function permit(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @dev Returns the current nonce for `owner`. This value must be
|
||||
* included whenever a signature is generated for {permit}.
|
||||
*
|
||||
* Every successful call to {permit} increases ``owner``'s nonce by one. This
|
||||
* prevents a signature from being used multiple times.
|
||||
*/
|
||||
function nonces(address owner) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
|
||||
*/
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function DOMAIN_SEPARATOR() external view returns (bytes32);
|
||||
}
|
||||
|
||||
interface ILixirVaultToken is IERC20, IERC20Permit {
|
||||
}
|
||||
|
||||
interface ILixirVault is ILixirVaultToken {
|
||||
function initialize(
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address _token0,
|
||||
address _token1,
|
||||
address _strategist,
|
||||
address _keeper,
|
||||
address _strategy
|
||||
) external;
|
||||
|
||||
function token0() external view returns (IERC20);
|
||||
|
||||
function token1() external view returns (IERC20);
|
||||
|
||||
function activeFee() external view returns (uint24);
|
||||
|
||||
function activePool() external view returns (IUniswapV3Pool);
|
||||
|
||||
function performanceFee() external view returns (uint24);
|
||||
|
||||
function strategist() external view returns (address);
|
||||
|
||||
function strategy() external view returns (address);
|
||||
|
||||
function keeper() external view returns (address);
|
||||
|
||||
function setKeeper(address _keeper) external;
|
||||
|
||||
function setStrategist(address _strategist) external;
|
||||
|
||||
function setStrategy(address _strategy) external;
|
||||
|
||||
function setPerformanceFee(uint24 newFee) external;
|
||||
|
||||
function mainPosition()
|
||||
external
|
||||
view
|
||||
returns (int24 tickLower, int24 tickUpper);
|
||||
|
||||
function rangePosition()
|
||||
external
|
||||
view
|
||||
returns (int24 tickLower, int24 tickUpper);
|
||||
|
||||
function rebalance(
|
||||
int24 mainTickLower,
|
||||
int24 mainTickUpper,
|
||||
int24 rangeTickLower0,
|
||||
int24 rangeTickUpper0,
|
||||
int24 rangeTickLower1,
|
||||
int24 rangeTickUpper1,
|
||||
uint24 fee
|
||||
) external;
|
||||
|
||||
function withdraw(
|
||||
uint256 shares,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address receiver,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amount0Out, uint256 amount1Out);
|
||||
|
||||
function withdrawFrom(
|
||||
address withdrawer,
|
||||
uint256 shares,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amount0Out, uint256 amount1Out);
|
||||
|
||||
function deposit(
|
||||
uint256 amount0Desired,
|
||||
uint256 amount1Desired,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline
|
||||
)
|
||||
external
|
||||
returns (
|
||||
uint256 shares,
|
||||
uint256 amount0,
|
||||
uint256 amount1
|
||||
);
|
||||
|
||||
function calculateTotals()
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 total0,
|
||||
uint256 total1,
|
||||
uint128 mL,
|
||||
uint128 rL
|
||||
);
|
||||
|
||||
function calculateTotalsFromTick(int24 virtualTick)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 total0,
|
||||
uint256 total1,
|
||||
uint128 mL,
|
||||
uint128 rL
|
||||
);
|
||||
}
|
||||
|
||||
interface ILixirVaultETH is ILixirVault {
|
||||
|
||||
enum TOKEN {ZERO, ONE}
|
||||
|
||||
function WETH_TOKEN() external view returns (TOKEN);
|
||||
|
||||
function depositETH(
|
||||
uint256 amountDesired,
|
||||
uint256 amountEthMin,
|
||||
uint256 amountMin,
|
||||
address recipient,
|
||||
uint256 deadline
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (
|
||||
uint256 shares,
|
||||
uint256 amountEthIn,
|
||||
uint256 amountIn
|
||||
);
|
||||
|
||||
function withdrawETHFrom(
|
||||
address withdrawer,
|
||||
uint256 shares,
|
||||
uint256 amountEthMin,
|
||||
uint256 amountMin,
|
||||
address payable recipient,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountEthOut, uint256 amountOut);
|
||||
|
||||
function withdrawETH(
|
||||
uint256 shares,
|
||||
uint256 amountEthMin,
|
||||
uint256 amountMin,
|
||||
address payable recipient,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountEthOut, uint256 amountOut);
|
||||
|
||||
receive() external payable;
|
||||
}
|
||||
116
contracts/mainnet/connectors/lixir/main.sol
Normal file
116
contracts/mainnet/connectors/lixir/main.sol
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
/**
|
||||
* @title Lixir Finance.
|
||||
* @dev Automated Liquidity Concentrator.
|
||||
*/
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { Helpers } from "./helpers.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract LixirResolver is Helpers, Events {
|
||||
/**
|
||||
* @dev Add liqudity to the vault
|
||||
* @notice Mint Lixir Vault Tokens
|
||||
* @param vault vault address
|
||||
* @param amount0Desired amount of tokenA
|
||||
* @param amount1Desired amount of tokenB
|
||||
* @param amount0Min amount of tokenA
|
||||
* @param amount1Min amount of tokenB
|
||||
* @param recipient recipient of the Lixir Vault Tokens
|
||||
* @param deadline unix timestamp
|
||||
* @param getIds ID to retrieve amtA
|
||||
* @param setId ID stores the amount of LP token
|
||||
*/
|
||||
function deposit(
|
||||
address payable vault,
|
||||
uint256 amount0Desired,
|
||||
uint256 amount1Desired,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline,
|
||||
uint256[] calldata getIds,
|
||||
uint256 setId
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
amount0Desired = getUint(getIds[0], amount0Desired);
|
||||
amount1Desired = getUint(getIds[1], amount1Desired);
|
||||
|
||||
(
|
||||
uint256 shares,
|
||||
uint256 amount0In,
|
||||
uint256 amount1In
|
||||
) = _deposit(
|
||||
vault,
|
||||
amount0Desired,
|
||||
amount1Desired,
|
||||
amount0Min,
|
||||
amount1Min,
|
||||
recipient,
|
||||
deadline
|
||||
);
|
||||
|
||||
setUint(setId, shares);
|
||||
|
||||
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
vault,
|
||||
shares,
|
||||
amount0In,
|
||||
amount1In
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Decrease Liquidity
|
||||
* @notice Withdraw Liquidity from Lixir Vault
|
||||
* @param vault Lixir vault address
|
||||
* @param shares the amount of Lixir Vault Tokens to remove
|
||||
* @param amount0Min Min amount of token0.
|
||||
* @param amount1Min Min amount of token1.
|
||||
* @param deadline unix timestamp
|
||||
* @param getId ID to retrieve LP token amounts
|
||||
* @param setIds stores the amount of output tokens
|
||||
*/
|
||||
function withdraw(
|
||||
address vault,
|
||||
uint256 shares,
|
||||
uint256 amount0Min,
|
||||
uint256 amount1Min,
|
||||
address recipient,
|
||||
uint256 deadline,
|
||||
uint256 getId,
|
||||
uint256[] calldata setIds
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
address vault = address(getUint(getId, uint256(vault))); // unsure of this...
|
||||
|
||||
(uint256 amount0Out, uint256 amount1Out) = _withdraw(
|
||||
vault,
|
||||
shares,
|
||||
amount0Min,
|
||||
amount1Min,
|
||||
recipient,
|
||||
deadline
|
||||
);
|
||||
|
||||
setUint(setIds[0], amount0Out);
|
||||
setUint(setIds[1], amount1Out);
|
||||
|
||||
_eventName = "LogWithdraw(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(vault, amount0Out, amount1Out);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2Lixir is LixirResolver {
|
||||
string public constant name = "Lixir-v1";
|
||||
}
|
||||
|
|
@ -9,15 +9,15 @@ const mineTx = async (tx: any) => {
|
|||
|
||||
const tokenMapping: Record<string, any> = {
|
||||
usdc: {
|
||||
impersonateSigner: "0xfcb19e6a322b27c06842a71e8c725399f049ae3a",
|
||||
impersonateSigner: "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503",
|
||||
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
||||
abi: [
|
||||
"function mint(address _to, uint256 _amount) external returns (bool);",
|
||||
"function transfer(address to, uint value)"
|
||||
],
|
||||
process: async function(owner: Signer | Provider, to: any, amt: any) {
|
||||
const contract = new ethers.Contract(this.address, this.abi, owner);
|
||||
|
||||
await mineTx(contract.mint(to, amt));
|
||||
await mineTx(contract.transfer(to, amt));
|
||||
},
|
||||
},
|
||||
dai: {
|
||||
|
|
|
|||
164
test/mainnet/lixir/lixir.test.ts
Normal file
164
test/mainnet/lixir/lixir.test.ts
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
import { expect } from "chai";
|
||||
import hre from "hardhat";
|
||||
const { waffle, ethers, network } = hre;
|
||||
const { provider, deployContract } = waffle;
|
||||
|
||||
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 { addLiquidity } from "../../../scripts/tests/addLiquidity";
|
||||
import { addresses } from "../../../scripts/tests/mainnet/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import type { Signer, Contract } from "ethers";
|
||||
|
||||
import { ConnectV2Lixir__factory, ILixirVault__factory } from "../../../typechain";
|
||||
|
||||
const USDC_WETH_VAULT = "0x453A9f40a24DbE3CdB4edC988aF9bfE0F5602b15"
|
||||
|
||||
const abiCoder = ethers.utils.defaultAbiCoder;
|
||||
|
||||
describe("Lixir", function() {
|
||||
const connectorName = "Lixir-v1";
|
||||
|
||||
let dsaWallet0: any;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: Contract;
|
||||
let vault: Contract;
|
||||
|
||||
const wallets = provider.getWallets();
|
||||
const [wallet0, wallet1, wallet2, wallet3] = wallets;
|
||||
before(async () => {
|
||||
await network.provider.send("evm_setAutomine", [false]);
|
||||
await network.provider.send("evm_setIntervalMining", [3000]);
|
||||
await network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
||||
blockNumber: 13298611,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(
|
||||
abis.core.connectorsV2,
|
||||
addresses.core.connectorsV2
|
||||
);
|
||||
|
||||
vault = await ethers.getContractAt(
|
||||
ILixirVault__factory.abi,
|
||||
USDC_WETH_VAULT
|
||||
);
|
||||
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2Lixir__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2,
|
||||
});
|
||||
console.log("Connector 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;
|
||||
});
|
||||
|
||||
it("Deposit ETH & USDC into DSA wallet", 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")
|
||||
);
|
||||
|
||||
await addLiquidity(
|
||||
"usdc",
|
||||
dsaWallet0.address,
|
||||
1000000 * 10**6 // USDC has 6 decimals
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function() {
|
||||
it("Should deposit successfully", async function() {
|
||||
const usdcAmount = ethers.BigNumber.from(10**6).mul(4000); // ~1 ETH
|
||||
const ethAmount = ethers.utils.parseEther("1"); // 1 ETH
|
||||
|
||||
const getIds = ["0", "0"];
|
||||
const setId = "0";
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "deposit",
|
||||
args: [ // get these right
|
||||
vault.address,
|
||||
usdcAmount,
|
||||
ethAmount,
|
||||
0, // any slippage lol
|
||||
0, // any slippage lol
|
||||
dsaWallet0.address,
|
||||
1740297687, // high deadline
|
||||
getIds,
|
||||
setId,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const tx = await dsaWallet0
|
||||
.connect(wallet0)
|
||||
.cast(...encodeSpells(spells), wallet1.address);
|
||||
const receipt = await tx.wait();
|
||||
|
||||
|
||||
console.log(await vault.balanceOf(wallet1.address));
|
||||
// console.log(await vault.balanceOf(dsaWallet0.address));
|
||||
// const dsaLvtBalance = await vault.balanceOf(dsaWallet0.address);
|
||||
// console.log(dsaLvtBalance);
|
||||
// expect(dsaLvtBalance).gte(0);
|
||||
});
|
||||
|
||||
// it("Should withdraw successfully", async function() {
|
||||
// const getId = "0";
|
||||
// const setIds = ["0", "0"];
|
||||
|
||||
// const data = await nftManager.positions(tokenIds[0]);
|
||||
// let data1 = await nftManager.positions(tokenIds[1]);
|
||||
|
||||
// const spells = [
|
||||
// {
|
||||
// connector: connectorName,
|
||||
// method: "withdraw",
|
||||
// args: [tokenIds[0], data.liquidity, 0, 0, getId, setIds],
|
||||
// },
|
||||
// {
|
||||
// connector: connectorName,
|
||||
// method: "withdraw",
|
||||
// args: [0, data1.liquidity, 0, 0, getId, setIds],
|
||||
// },
|
||||
// ];
|
||||
|
||||
// const tx = await dsaWallet0
|
||||
// .connect(wallet0)
|
||||
// .cast(...encodeSpells(spells), wallet1.address);
|
||||
// const receipt = await tx.wait();
|
||||
|
||||
// data1 = await nftManager.positions(tokenIds[1]);
|
||||
// expect(data1.liquidity.toNumber()).to.be.equals(0);
|
||||
// });
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user