mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Merge branch 'main' into pooltogether-connector
This commit is contained in:
commit
e7788adac9
62
contracts/mainnet/connectors/b.protocol/compound/events.sol
Normal file
62
contracts/mainnet/connectors/b.protocol/compound/events.sol
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
contract Events {
|
||||||
|
event LogDeposit(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdraw(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogBorrow(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogPayback(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogDepositCToken(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 cTokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdrawCToken(
|
||||||
|
address indexed token,
|
||||||
|
address cToken,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 cTokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogLiquidate(
|
||||||
|
address indexed borrower,
|
||||||
|
address indexed tokenToPay,
|
||||||
|
address indexed tokenInReturn,
|
||||||
|
uint256 tokenAmt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
);
|
||||||
|
}
|
26
contracts/mainnet/connectors/b.protocol/compound/helpers.sol
Normal file
26
contracts/mainnet/connectors/b.protocol/compound/helpers.sol
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
import { DSMath } from "./../../../common/math.sol";
|
||||||
|
import { Basic } from "./../../../common/basic.sol";
|
||||||
|
import { ComptrollerInterface, CompoundMappingInterface, BComptrollerInterface } from "./interface.sol";
|
||||||
|
|
||||||
|
abstract contract Helpers is DSMath, Basic {
|
||||||
|
/**
|
||||||
|
* @dev Compound Comptroller
|
||||||
|
*/
|
||||||
|
ComptrollerInterface internal constant troller = ComptrollerInterface(0x9dB10B9429989cC13408d7368644D4A1CB704ea3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Compound Mapping
|
||||||
|
*/
|
||||||
|
CompoundMappingInterface internal constant compMapping = CompoundMappingInterface(0xe7a85d0adDB972A4f0A4e57B698B37f171519e88);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev B.Compound Mapping
|
||||||
|
*/
|
||||||
|
function getMapping(string calldata tokenId) public returns(address token, address btoken) {
|
||||||
|
address ctoken;
|
||||||
|
(token, ctoken) = compMapping.getMapping(tokenId);
|
||||||
|
btoken = BComptrollerInterface(address(troller)).c2b(ctoken);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
interface CTokenInterface {
|
||||||
|
function mint(uint mintAmount) external returns (uint);
|
||||||
|
function redeem(uint redeemTokens) external returns (uint);
|
||||||
|
function borrow(uint borrowAmount) external returns (uint);
|
||||||
|
function repayBorrow(uint repayAmount) external returns (uint);
|
||||||
|
function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint); // For ERC20
|
||||||
|
function liquidateBorrow(address borrower, uint repayAmount, address cTokenCollateral) external returns (uint);
|
||||||
|
|
||||||
|
function borrowBalanceCurrent(address account) external returns (uint);
|
||||||
|
function redeemUnderlying(uint redeemAmount) external returns (uint);
|
||||||
|
function exchangeRateCurrent() external returns (uint);
|
||||||
|
|
||||||
|
function balanceOf(address owner) external view returns (uint256 balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CETHInterface {
|
||||||
|
function mint() external payable;
|
||||||
|
function repayBorrow() external payable;
|
||||||
|
function repayBorrowBehalf(address borrower) external payable;
|
||||||
|
function liquidateBorrow(address borrower, address cTokenCollateral) external payable;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComptrollerInterface {
|
||||||
|
function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);
|
||||||
|
function exitMarket(address cTokenAddress) external returns (uint);
|
||||||
|
function getAssetsIn(address account) external view returns (address[] memory);
|
||||||
|
function getAccountLiquidity(address account) external view returns (uint, uint, uint);
|
||||||
|
function claimComp(address) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CompoundMappingInterface {
|
||||||
|
function cTokenMapping(string calldata tokenId) external view returns (address);
|
||||||
|
function getMapping(string calldata tokenId) external view returns (address, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BComptrollerInterface {
|
||||||
|
function c2b(address ctoken) external view returns(address);
|
||||||
|
}
|
347
contracts/mainnet/connectors/b.protocol/compound/main.sol
Normal file
347
contracts/mainnet/connectors/b.protocol/compound/main.sol
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title B.Compound.
|
||||||
|
* @dev Lending & Borrowing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||||
|
import { Stores } from "../../../common/stores.sol";
|
||||||
|
import { Helpers } from "./helpers.sol";
|
||||||
|
import { Events } from "./events.sol";
|
||||||
|
import { CETHInterface, CTokenInterface } from "./interface.sol";
|
||||||
|
|
||||||
|
abstract contract BCompoundResolver is Events, Helpers {
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token.
|
||||||
|
* @notice Deposit a token to Compound for lending / collaterization.
|
||||||
|
* @param token The address of the token to deposit. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens deposited.
|
||||||
|
*/
|
||||||
|
function depositRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
if (token == ethAddr) {
|
||||||
|
_amt = _amt == uint(-1) ? address(this).balance : _amt;
|
||||||
|
CETHInterface(cToken).mint{value: _amt}();
|
||||||
|
} else {
|
||||||
|
TokenInterface tokenContract = TokenInterface(token);
|
||||||
|
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
|
||||||
|
approve(tokenContract, cToken, _amt);
|
||||||
|
require(CTokenInterface(cToken).mint(_amt) == 0, "deposit-failed");
|
||||||
|
}
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogDeposit(address,address,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token using the Mapping.
|
||||||
|
* @notice Deposit a token to Compound for lending / collaterization.
|
||||||
|
* @param tokenId The token id of the token to deposit.(For eg: ETH-A)
|
||||||
|
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens deposited.
|
||||||
|
*/
|
||||||
|
function deposit(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = depositRaw(token, cToken, amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw ETH/ERC20_Token.
|
||||||
|
* @notice Withdraw deposited token from Compound
|
||||||
|
* @param token The address of the token to withdraw. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param amt The amount of the token to withdraw. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens withdrawn.
|
||||||
|
*/
|
||||||
|
function withdrawRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
CTokenInterface cTokenContract = CTokenInterface(cToken);
|
||||||
|
if (_amt == uint(-1)) {
|
||||||
|
TokenInterface tokenContract = TokenInterface(token);
|
||||||
|
uint initialBal = token == ethAddr ? address(this).balance : tokenContract.balanceOf(address(this));
|
||||||
|
require(cTokenContract.redeem(cTokenContract.balanceOf(address(this))) == 0, "full-withdraw-failed");
|
||||||
|
uint finalBal = token == ethAddr ? address(this).balance : tokenContract.balanceOf(address(this));
|
||||||
|
_amt = finalBal - initialBal;
|
||||||
|
} else {
|
||||||
|
require(cTokenContract.redeemUnderlying(_amt) == 0, "withdraw-failed");
|
||||||
|
}
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogWithdraw(address,address,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw ETH/ERC20_Token using the Mapping.
|
||||||
|
* @notice Withdraw deposited token from Compound
|
||||||
|
* @param tokenId The token id of the token to withdraw.(For eg: ETH-A)
|
||||||
|
* @param amt The amount of the token to withdraw. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens withdrawn.
|
||||||
|
*/
|
||||||
|
function withdraw(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = withdrawRaw(token, cToken, amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Borrow ETH/ERC20_Token.
|
||||||
|
* @notice Borrow a token using Compound
|
||||||
|
* @param token The address of the token to borrow. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param amt The amount of the token to borrow.
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens borrowed.
|
||||||
|
*/
|
||||||
|
function borrowRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
require(CTokenInterface(cToken).borrow(_amt) == 0, "borrow-failed");
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogBorrow(address,address,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Borrow ETH/ERC20_Token using the Mapping.
|
||||||
|
* @notice Borrow a token using Compound
|
||||||
|
* @param tokenId The token id of the token to borrow.(For eg: DAI-A)
|
||||||
|
* @param amt The amount of the token to borrow.
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens borrowed.
|
||||||
|
*/
|
||||||
|
function borrow(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = borrowRaw(token, cToken, amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Payback borrowed ETH/ERC20_Token.
|
||||||
|
* @notice Payback debt owed.
|
||||||
|
* @param token The address of the token to payback. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param amt The amount of the token to payback. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens paid back.
|
||||||
|
*/
|
||||||
|
function paybackRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
CTokenInterface cTokenContract = CTokenInterface(cToken);
|
||||||
|
_amt = _amt == uint(-1) ? cTokenContract.borrowBalanceCurrent(address(this)) : _amt;
|
||||||
|
|
||||||
|
if (token == ethAddr) {
|
||||||
|
require(address(this).balance >= _amt, "not-enough-eth");
|
||||||
|
CETHInterface(cToken).repayBorrow{value: _amt}();
|
||||||
|
} else {
|
||||||
|
TokenInterface tokenContract = TokenInterface(token);
|
||||||
|
require(tokenContract.balanceOf(address(this)) >= _amt, "not-enough-token");
|
||||||
|
approve(tokenContract, cToken, _amt);
|
||||||
|
require(cTokenContract.repayBorrow(_amt) == 0, "repay-failed.");
|
||||||
|
}
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogPayback(address,address,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Payback borrowed ETH/ERC20_Token using the Mapping.
|
||||||
|
* @notice Payback debt owed.
|
||||||
|
* @param tokenId The token id of the token to payback.(For eg: COMP-A)
|
||||||
|
* @param amt The amount of the token to payback. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens paid back.
|
||||||
|
*/
|
||||||
|
function payback(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = paybackRaw(token, cToken, amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token.
|
||||||
|
* @notice Same as depositRaw. The only difference is this method stores cToken amount in set ID.
|
||||||
|
* @param token The address of the token to deposit. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of cTokens received.
|
||||||
|
*/
|
||||||
|
function depositCTokenRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
CTokenInterface ctokenContract = CTokenInterface(cToken);
|
||||||
|
uint initialBal = ctokenContract.balanceOf(address(this));
|
||||||
|
|
||||||
|
if (token == ethAddr) {
|
||||||
|
_amt = _amt == uint(-1) ? address(this).balance : _amt;
|
||||||
|
CETHInterface(cToken).mint{value: _amt}();
|
||||||
|
} else {
|
||||||
|
TokenInterface tokenContract = TokenInterface(token);
|
||||||
|
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
|
||||||
|
approve(tokenContract, cToken, _amt);
|
||||||
|
require(ctokenContract.mint(_amt) == 0, "deposit-ctoken-failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint _cAmt;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint finalBal = ctokenContract.balanceOf(address(this));
|
||||||
|
_cAmt = sub(finalBal, initialBal);
|
||||||
|
|
||||||
|
setUint(setId, _cAmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventName = "LogDepositCToken(address,address,uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, _amt, _cAmt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token using the Mapping.
|
||||||
|
* @notice Same as deposit. The only difference is this method stores cToken amount in set ID.
|
||||||
|
* @param tokenId The token id of the token to depositCToken.(For eg: DAI-A)
|
||||||
|
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of cTokens received.
|
||||||
|
*/
|
||||||
|
function depositCToken(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = depositCTokenRaw(token, cToken, amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw CETH/CERC20_Token using cToken Amt.
|
||||||
|
* @notice Same as withdrawRaw. The only difference is this method fetch cToken amount in get ID.
|
||||||
|
* @param token The address of the token to withdraw. (For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||||
|
* @param cToken The address of the corresponding cToken.
|
||||||
|
* @param cTokenAmt The amount of cTokens to withdraw
|
||||||
|
* @param getId ID to retrieve cTokenAmt
|
||||||
|
* @param setId ID stores the amount of tokens withdrawn.
|
||||||
|
*/
|
||||||
|
function withdrawCTokenRaw(
|
||||||
|
address token,
|
||||||
|
address cToken,
|
||||||
|
uint cTokenAmt,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
) public payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _cAmt = getUint(getId, cTokenAmt);
|
||||||
|
require(token != address(0) && cToken != address(0), "invalid token/ctoken address");
|
||||||
|
|
||||||
|
CTokenInterface cTokenContract = CTokenInterface(cToken);
|
||||||
|
TokenInterface tokenContract = TokenInterface(token);
|
||||||
|
_cAmt = _cAmt == uint(-1) ? cTokenContract.balanceOf(address(this)) : _cAmt;
|
||||||
|
|
||||||
|
uint withdrawAmt;
|
||||||
|
{
|
||||||
|
uint initialBal = token != ethAddr ? tokenContract.balanceOf(address(this)) : address(this).balance;
|
||||||
|
require(cTokenContract.redeem(_cAmt) == 0, "redeem-failed");
|
||||||
|
uint finalBal = token != ethAddr ? tokenContract.balanceOf(address(this)) : address(this).balance;
|
||||||
|
|
||||||
|
withdrawAmt = sub(finalBal, initialBal);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUint(setId, withdrawAmt);
|
||||||
|
|
||||||
|
_eventName = "LogWithdrawCToken(address,address,uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(token, cToken, withdrawAmt, _cAmt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw CETH/CERC20_Token using cToken Amt & the Mapping.
|
||||||
|
* @notice Same as withdraw. The only difference is this method fetch cToken amount in get ID.
|
||||||
|
* @param tokenId The token id of the token to withdraw CToken.(For eg: ETH-A)
|
||||||
|
* @param cTokenAmt The amount of cTokens to withdraw
|
||||||
|
* @param getId ID to retrieve cTokenAmt
|
||||||
|
* @param setId ID stores the amount of tokens withdrawn.
|
||||||
|
*/
|
||||||
|
function withdrawCToken(
|
||||||
|
string calldata tokenId,
|
||||||
|
uint cTokenAmt,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
(address token, address cToken) = getMapping(tokenId);
|
||||||
|
(_eventName, _eventParam) = withdrawCTokenRaw(token, cToken, cTokenAmt, getId, setId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectV2BCompound is BCompoundResolver {
|
||||||
|
string public name = "B.Compound-v1.0";
|
||||||
|
}
|
22
contracts/mainnet/connectors/b.protocol/liquity/events.sol
Normal file
22
contracts/mainnet/connectors/b.protocol/liquity/events.sol
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
|
contract Events {
|
||||||
|
|
||||||
|
/* Stability Pool */
|
||||||
|
event LogStabilityDeposit(
|
||||||
|
address indexed borrower,
|
||||||
|
uint amount,
|
||||||
|
uint lqtyGain,
|
||||||
|
uint getDepositId,
|
||||||
|
uint setDepositId,
|
||||||
|
uint setLqtyGainId
|
||||||
|
);
|
||||||
|
event LogStabilityWithdraw(
|
||||||
|
address indexed borrower,
|
||||||
|
uint numShares,
|
||||||
|
uint lqtyGain,
|
||||||
|
uint getWithdrawId,
|
||||||
|
uint setWithdrawId,
|
||||||
|
uint setLqtyGainId
|
||||||
|
);
|
||||||
|
}
|
18
contracts/mainnet/connectors/b.protocol/liquity/helpers.sol
Normal file
18
contracts/mainnet/connectors/b.protocol/liquity/helpers.sol
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
|
import { DSMath } from "../../../common/math.sol";
|
||||||
|
import { Basic } from "../../../common/basic.sol";
|
||||||
|
|
||||||
|
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||||
|
|
||||||
|
import {
|
||||||
|
StabilityPoolLike,
|
||||||
|
BAMMLike
|
||||||
|
} from "./interface.sol";
|
||||||
|
|
||||||
|
abstract contract Helpers is DSMath, Basic {
|
||||||
|
StabilityPoolLike internal constant stabilityPool = StabilityPoolLike(0x66017D22b0f8556afDd19FC67041899Eb65a21bb);
|
||||||
|
TokenInterface internal constant lqtyToken = TokenInterface(0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D);
|
||||||
|
TokenInterface internal constant lusdToken = TokenInterface(0x5f98805A4E8be255a32880FDeC7F6728C6568bA0);
|
||||||
|
BAMMLike internal constant BAMM = BAMMLike(0x0d3AbAA7E088C2c82f54B2f47613DA438ea8C598);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
|
interface StabilityPoolLike {
|
||||||
|
function provideToSP(uint _amount, address _frontEndTag) external;
|
||||||
|
function withdrawFromSP(uint _amount) external;
|
||||||
|
function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external;
|
||||||
|
function getDepositorETHGain(address _depositor) external view returns (uint);
|
||||||
|
function getDepositorLQTYGain(address _depositor) external view returns (uint);
|
||||||
|
function getCompoundedLUSDDeposit(address _depositor) external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BAMMLike {
|
||||||
|
function deposit(uint lusdAmount) external;
|
||||||
|
function withdraw(uint numShares) external;
|
||||||
|
function balanceOf(address a) external view returns(uint);
|
||||||
|
function totalSupply() external view returns(uint);
|
||||||
|
}
|
86
contracts/mainnet/connectors/b.protocol/liquity/main.sol
Normal file
86
contracts/mainnet/connectors/b.protocol/liquity/main.sol
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title B.Liquity.
|
||||||
|
* @dev Lending & Borrowing.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
StabilityPoolLike,
|
||||||
|
BAMMLike
|
||||||
|
} from "./interface.sol";
|
||||||
|
import { Stores } from "../../../common/stores.sol";
|
||||||
|
import { Helpers } from "./helpers.sol";
|
||||||
|
import { Events } from "./events.sol";
|
||||||
|
|
||||||
|
abstract contract BLiquityResolver is Events, Helpers {
|
||||||
|
/* Begin: Stability Pool */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit LUSD into Stability Pool
|
||||||
|
* @notice Deposit LUSD into Stability Pool
|
||||||
|
* @param amount Amount of LUSD to deposit into Stability Pool
|
||||||
|
* @param getDepositId Optional storage slot to retrieve the amount of LUSD from
|
||||||
|
* @param setDepositId Optional storage slot to store the final amount of LUSD deposited
|
||||||
|
* @param setLqtyGainId Optional storage slot to store any LQTY gains in
|
||||||
|
*/
|
||||||
|
function deposit(
|
||||||
|
uint amount,
|
||||||
|
uint getDepositId,
|
||||||
|
uint setDepositId,
|
||||||
|
uint setLqtyGainId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
amount = getUint(getDepositId, amount);
|
||||||
|
|
||||||
|
amount = amount == uint(-1) ? lusdToken.balanceOf(address(this)) : amount;
|
||||||
|
|
||||||
|
uint lqtyBalanceBefore = lqtyToken.balanceOf(address(this));
|
||||||
|
|
||||||
|
lusdToken.approve(address(BAMM), amount);
|
||||||
|
BAMM.deposit(amount);
|
||||||
|
|
||||||
|
uint lqtyBalanceAfter = lqtyToken.balanceOf(address(this));
|
||||||
|
uint lqtyGain = sub(lqtyBalanceAfter, lqtyBalanceBefore);
|
||||||
|
|
||||||
|
setUint(setDepositId, amount);
|
||||||
|
setUint(setLqtyGainId, lqtyGain);
|
||||||
|
|
||||||
|
_eventName = "LogStabilityDeposit(address,uint256,uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(address(this), amount,lqtyGain, getDepositId, setDepositId, setLqtyGainId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw user deposited LUSD from Stability Pool
|
||||||
|
* @notice Withdraw LUSD from Stability Pool
|
||||||
|
* @param numShares amount of shares to withdraw from the BAMM
|
||||||
|
* @param getWithdrawId Optional storage slot to retrieve the amount of LUSD to withdraw from
|
||||||
|
* @param setWithdrawId Optional storage slot to store the withdrawn LUSD
|
||||||
|
* @param setLqtyGainId Optional storage slot to store any LQTY gains in
|
||||||
|
*/
|
||||||
|
function withdraw(
|
||||||
|
uint numShares,
|
||||||
|
uint getWithdrawId,
|
||||||
|
uint setWithdrawId,
|
||||||
|
uint setLqtyGainId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
numShares = getUint(getWithdrawId, numShares);
|
||||||
|
|
||||||
|
numShares = numShares == uint(-1) ? BAMM.balanceOf(address(this)) : numShares;
|
||||||
|
|
||||||
|
uint lqtyBalanceBefore = lqtyToken.balanceOf(address(this));
|
||||||
|
|
||||||
|
BAMM.withdraw(numShares);
|
||||||
|
|
||||||
|
uint lqtyBalanceAfter = lqtyToken.balanceOf(address(this));
|
||||||
|
uint lqtyGain = sub(lqtyBalanceAfter, lqtyBalanceBefore);
|
||||||
|
|
||||||
|
setUint(setWithdrawId, numShares);
|
||||||
|
setUint(setLqtyGainId, lqtyGain);
|
||||||
|
|
||||||
|
_eventName = "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(address(this), numShares, lqtyGain, getWithdrawId, setWithdrawId, setLqtyGainId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectV2BLiquity is BLiquityResolver {
|
||||||
|
string public name = "B.Liquity-v1";
|
||||||
|
}
|
26
contracts/mainnet/connectors/b.protocol/makerdao/events.sol
Normal file
26
contracts/mainnet/connectors/b.protocol/makerdao/events.sol
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
contract Events {
|
||||||
|
event LogOpen(uint256 indexed vault, bytes32 indexed ilk);
|
||||||
|
event LogClose(uint256 indexed vault, bytes32 indexed ilk);
|
||||||
|
event LogTransfer(uint256 indexed vault, bytes32 indexed ilk, address newOwner);
|
||||||
|
event LogDeposit(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogWithdraw(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogBorrow(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogPayback(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogWithdrawLiquidated(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogExitDai(uint256 indexed vault, bytes32 indexed ilk, uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogDepositDai(uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
event LogWithdrawDai(uint256 tokenAmt, uint256 getId, uint256 setId);
|
||||||
|
|
||||||
|
event LogDepositAndBorrow(
|
||||||
|
uint256 indexed vault,
|
||||||
|
bytes32 indexed ilk,
|
||||||
|
uint256 depositAmt,
|
||||||
|
uint256 borrowAmt,
|
||||||
|
uint256 getIdDeposit,
|
||||||
|
uint256 getIdBorrow,
|
||||||
|
uint256 setIdDeposit,
|
||||||
|
uint256 setIdBorrow
|
||||||
|
);
|
||||||
|
}
|
130
contracts/mainnet/connectors/b.protocol/makerdao/helpers.sol
Normal file
130
contracts/mainnet/connectors/b.protocol/makerdao/helpers.sol
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
import { DSMath } from "../../../common/math.sol";
|
||||||
|
import { Basic } from "../../../common/basic.sol";
|
||||||
|
import { TokenInterface } from "./../../../common/interfaces.sol";
|
||||||
|
import { BManagerLike, DaiJoinInterface, PotLike, VatLike, JugLike } from "./interface.sol";
|
||||||
|
|
||||||
|
abstract contract Helpers is DSMath, Basic {
|
||||||
|
/**
|
||||||
|
* @dev Manager Interface
|
||||||
|
*/
|
||||||
|
BManagerLike internal constant managerContract = BManagerLike(0x3f30c2381CD8B917Dd96EB2f1A4F96D91324BBed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev DAI Join
|
||||||
|
*/
|
||||||
|
DaiJoinInterface internal constant daiJoinContract = DaiJoinInterface(0x9759A6Ac90977b93B58547b4A71c78317f391A28);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Pot
|
||||||
|
*/
|
||||||
|
PotLike internal constant potContract = PotLike(0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Maker MCD Jug Address.
|
||||||
|
*/
|
||||||
|
JugLike internal constant mcdJug = JugLike(0x19c0976f590D67707E62397C87829d896Dc0f1F1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Return Close Vault Address.
|
||||||
|
*/
|
||||||
|
address internal constant giveAddr = 0x4dD58550eb15190a5B3DfAE28BB14EeC181fC267;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get Vault's ilk.
|
||||||
|
*/
|
||||||
|
function getVaultData(uint vault) internal view returns (bytes32 ilk, address urn) {
|
||||||
|
ilk = managerContract.ilks(vault);
|
||||||
|
urn = managerContract.urns(vault);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gem Join address is ETH type collateral.
|
||||||
|
*/
|
||||||
|
function isEth(address tknAddr) internal pure returns (bool) {
|
||||||
|
return tknAddr == wethAddr ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get Vault Debt Amount.
|
||||||
|
*/
|
||||||
|
function _getVaultDebt(
|
||||||
|
address vat,
|
||||||
|
bytes32 ilk,
|
||||||
|
address urn,
|
||||||
|
uint vault
|
||||||
|
) internal view returns (uint wad) {
|
||||||
|
(, uint rate,,,) = VatLike(vat).ilks(ilk);
|
||||||
|
(, uint art) = VatLike(vat).urns(ilk, urn);
|
||||||
|
uint cushion = managerContract.cushion(vault);
|
||||||
|
art = add(art, cushion);
|
||||||
|
uint dai = VatLike(vat).dai(urn);
|
||||||
|
|
||||||
|
uint rad = sub(mul(art, rate), dai);
|
||||||
|
wad = rad / RAY;
|
||||||
|
|
||||||
|
wad = mul(wad, RAY) < rad ? wad + 1 : wad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get Borrow Amount.
|
||||||
|
*/
|
||||||
|
function _getBorrowAmt(
|
||||||
|
address vat,
|
||||||
|
address urn,
|
||||||
|
bytes32 ilk,
|
||||||
|
uint amt
|
||||||
|
) internal returns (int dart)
|
||||||
|
{
|
||||||
|
uint rate = mcdJug.drip(ilk);
|
||||||
|
uint dai = VatLike(vat).dai(urn);
|
||||||
|
if (dai < mul(amt, RAY)) {
|
||||||
|
dart = toInt(sub(mul(amt, RAY), dai) / rate);
|
||||||
|
dart = mul(uint(dart), rate) < mul(amt, RAY) ? dart + 1 : dart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get Payback Amount.
|
||||||
|
*/
|
||||||
|
function _getWipeAmt(
|
||||||
|
address vat,
|
||||||
|
uint amt,
|
||||||
|
address urn,
|
||||||
|
bytes32 ilk,
|
||||||
|
uint vault
|
||||||
|
) internal view returns (int dart)
|
||||||
|
{
|
||||||
|
(, uint rate,,,) = VatLike(vat).ilks(ilk);
|
||||||
|
(, uint art) = VatLike(vat).urns(ilk, urn);
|
||||||
|
uint cushion = managerContract.cushion(vault);
|
||||||
|
art = add(art, cushion);
|
||||||
|
dart = toInt(amt / rate);
|
||||||
|
dart = uint(dart) <= art ? - dart : - toInt(art);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Convert String to bytes32.
|
||||||
|
*/
|
||||||
|
function stringToBytes32(string memory str) internal pure returns (bytes32 result) {
|
||||||
|
require(bytes(str).length != 0, "string-empty");
|
||||||
|
// solium-disable-next-line security/no-inline-assembly
|
||||||
|
assembly {
|
||||||
|
result := mload(add(str, 32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get vault ID. If `vault` is 0, get last opened vault.
|
||||||
|
*/
|
||||||
|
function getVault(uint vault) internal view returns (uint _vault) {
|
||||||
|
if (vault == 0) {
|
||||||
|
require(managerContract.count(address(this)) > 0, "no-vault-opened");
|
||||||
|
_vault = managerContract.last(address(this));
|
||||||
|
} else {
|
||||||
|
_vault = vault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||||
|
|
||||||
|
interface ManagerLike {
|
||||||
|
function cdpCan(address, uint, address) external view returns (uint);
|
||||||
|
function ilks(uint) external view returns (bytes32);
|
||||||
|
function last(address) external view returns (uint);
|
||||||
|
function count(address) external view returns (uint);
|
||||||
|
function owns(uint) external view returns (address);
|
||||||
|
function urns(uint) external view returns (address);
|
||||||
|
function vat() external view returns (address);
|
||||||
|
function open(bytes32, address) external returns (uint);
|
||||||
|
function give(uint, address) external;
|
||||||
|
function frob(uint, int, int) external;
|
||||||
|
function flux(uint, address, uint) external;
|
||||||
|
function move(uint, address, uint) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BManagerLike is ManagerLike {
|
||||||
|
function cushion(uint) external view returns (uint);
|
||||||
|
function cdpi() external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VatLike {
|
||||||
|
function can(address, address) external view returns (uint);
|
||||||
|
function ilks(bytes32) external view returns (uint, uint, uint, uint, uint);
|
||||||
|
function dai(address) external view returns (uint);
|
||||||
|
function urns(bytes32, address) external view returns (uint, uint);
|
||||||
|
function frob(
|
||||||
|
bytes32,
|
||||||
|
address,
|
||||||
|
address,
|
||||||
|
address,
|
||||||
|
int,
|
||||||
|
int
|
||||||
|
) external;
|
||||||
|
function hope(address) external;
|
||||||
|
function move(address, address, uint) external;
|
||||||
|
function gem(bytes32, address) external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenJoinInterface {
|
||||||
|
function dec() external returns (uint);
|
||||||
|
function gem() external returns (TokenInterface);
|
||||||
|
function join(address, uint) external payable;
|
||||||
|
function exit(address, uint) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DaiJoinInterface {
|
||||||
|
function vat() external returns (VatLike);
|
||||||
|
function dai() external returns (TokenInterface);
|
||||||
|
function join(address, uint) external payable;
|
||||||
|
function exit(address, uint) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JugLike {
|
||||||
|
function drip(bytes32) external returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PotLike {
|
||||||
|
function pie(address) external view returns (uint);
|
||||||
|
function drip() external returns (uint);
|
||||||
|
function join(uint) external;
|
||||||
|
function exit(uint) external;
|
||||||
|
}
|
521
contracts/mainnet/connectors/b.protocol/makerdao/main.sol
Normal file
521
contracts/mainnet/connectors/b.protocol/makerdao/main.sol
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title MakerDAO.
|
||||||
|
* @dev Collateralized Borrowing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TokenInterface, AccountInterface } from "./../../../common/interfaces.sol";
|
||||||
|
import { Helpers } from "./helpers.sol";
|
||||||
|
import { Events } from "./events.sol";
|
||||||
|
import { VatLike, TokenJoinInterface } from "./interface.sol";
|
||||||
|
|
||||||
|
abstract contract BMakerResolver is Helpers, Events {
|
||||||
|
/**
|
||||||
|
* @dev Open Vault
|
||||||
|
* @notice Open a MakerDAO Vault
|
||||||
|
* @param colType Type of Collateral.(eg: 'ETH-A')
|
||||||
|
*/
|
||||||
|
function open(string calldata colType) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
bytes32 ilk = stringToBytes32(colType);
|
||||||
|
require(instaMapping.gemJoinMapping(ilk) != address(0), "wrong-col-type");
|
||||||
|
uint256 vault = managerContract.open(ilk, address(this));
|
||||||
|
|
||||||
|
_eventName = "LogOpen(uint256,bytes32)";
|
||||||
|
_eventParam = abi.encode(vault, ilk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Close Vault
|
||||||
|
* @notice Close a MakerDAO Vault
|
||||||
|
* @param vault Vault ID to close.
|
||||||
|
*/
|
||||||
|
function close(uint256 vault) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
(uint ink, uint art) = VatLike(managerContract.vat()).urns(ilk, urn);
|
||||||
|
|
||||||
|
require(ink == 0 && art == 0, "vault-has-assets");
|
||||||
|
require(managerContract.owns(_vault) == address(this), "not-owner");
|
||||||
|
|
||||||
|
managerContract.give(_vault, giveAddr);
|
||||||
|
|
||||||
|
_eventName = "LogClose(uint256,bytes32)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer Vault
|
||||||
|
* @notice Transfer a MakerDAO Vault to "nextOwner"
|
||||||
|
* @param vault Vault ID to close.
|
||||||
|
* @param nextOwner Address of the next owner of the vault.
|
||||||
|
*/
|
||||||
|
function transfer(
|
||||||
|
uint vault,
|
||||||
|
address nextOwner
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
require(AccountInterface(address(this)).isAuth(nextOwner), "nextOwner-is-not-auth");
|
||||||
|
|
||||||
|
uint256 _vault = getVault(vault);
|
||||||
|
(bytes32 ilk,) = getVaultData(_vault);
|
||||||
|
|
||||||
|
require(managerContract.owns(_vault) == address(this), "not-owner");
|
||||||
|
|
||||||
|
managerContract.give(_vault, nextOwner);
|
||||||
|
|
||||||
|
_eventName = "LogTransfer(uint256,bytes32,address)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, nextOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token Collateral.
|
||||||
|
* @notice Deposit collateral to a MakerDAO vault
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt The amount of tokens to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens deposited.
|
||||||
|
*/
|
||||||
|
function deposit(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
|
||||||
|
address colAddr = instaMapping.gemJoinMapping(ilk);
|
||||||
|
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
|
||||||
|
TokenInterface tokenContract = tokenJoinContract.gem();
|
||||||
|
|
||||||
|
if (isEth(address(tokenContract))) {
|
||||||
|
_amt = _amt == uint(-1) ? address(this).balance : _amt;
|
||||||
|
tokenContract.deposit{value: _amt}();
|
||||||
|
} else {
|
||||||
|
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
approve(tokenContract, address(colAddr), _amt);
|
||||||
|
tokenJoinContract.join(urn, _amt);
|
||||||
|
|
||||||
|
managerContract.frob(
|
||||||
|
_vault,
|
||||||
|
toInt(convertTo18(tokenJoinContract.dec(), _amt)),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogDeposit(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw ETH/ERC20_Token Collateral.
|
||||||
|
* @notice Withdraw collateral from a MakerDAO vault
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt The amount of tokens to withdraw. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of tokens withdrawn.
|
||||||
|
*/
|
||||||
|
function withdraw(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
|
||||||
|
address colAddr = instaMapping.gemJoinMapping(ilk);
|
||||||
|
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
|
||||||
|
|
||||||
|
uint _amt18;
|
||||||
|
if (_amt == uint(-1)) {
|
||||||
|
(_amt18,) = VatLike(managerContract.vat()).urns(ilk, urn);
|
||||||
|
_amt = convert18ToDec(tokenJoinContract.dec(), _amt18);
|
||||||
|
} else {
|
||||||
|
_amt18 = convertTo18(tokenJoinContract.dec(), _amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
managerContract.frob(
|
||||||
|
_vault,
|
||||||
|
-toInt(_amt18),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
managerContract.flux(
|
||||||
|
_vault,
|
||||||
|
address(this),
|
||||||
|
_amt18
|
||||||
|
);
|
||||||
|
|
||||||
|
TokenInterface tokenContract = tokenJoinContract.gem();
|
||||||
|
|
||||||
|
if (isEth(address(tokenContract))) {
|
||||||
|
tokenJoinContract.exit(address(this), _amt);
|
||||||
|
tokenContract.withdraw(_amt);
|
||||||
|
} else {
|
||||||
|
tokenJoinContract.exit(address(this), _amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogWithdraw(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Borrow DAI.
|
||||||
|
* @notice Borrow DAI using a MakerDAO vault
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt The amount of DAI to borrow.
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of DAI borrowed.
|
||||||
|
*/
|
||||||
|
function borrow(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
|
||||||
|
VatLike vatContract = VatLike(managerContract.vat());
|
||||||
|
|
||||||
|
managerContract.frob(
|
||||||
|
_vault,
|
||||||
|
0,
|
||||||
|
_getBorrowAmt(
|
||||||
|
address(vatContract),
|
||||||
|
urn,
|
||||||
|
ilk,
|
||||||
|
_amt
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
managerContract.move(
|
||||||
|
_vault,
|
||||||
|
address(this),
|
||||||
|
toRad(_amt)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (vatContract.can(address(this), address(daiJoinContract)) == 0) {
|
||||||
|
vatContract.hope(address(daiJoinContract));
|
||||||
|
}
|
||||||
|
|
||||||
|
daiJoinContract.exit(address(this), _amt);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogBorrow(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Payback borrowed DAI.
|
||||||
|
* @notice Payback DAI debt owed by a MakerDAO vault
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt The amount of DAI to payback. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of DAI paid back.
|
||||||
|
*/
|
||||||
|
function payback(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
|
||||||
|
address vat = managerContract.vat();
|
||||||
|
|
||||||
|
uint _maxDebt = _getVaultDebt(vat, ilk, urn, vault);
|
||||||
|
|
||||||
|
_amt = _amt == uint(-1) ? _maxDebt : _amt;
|
||||||
|
|
||||||
|
require(_maxDebt >= _amt, "paying-excess-debt");
|
||||||
|
|
||||||
|
approve(daiJoinContract.dai(), address(daiJoinContract), _amt);
|
||||||
|
daiJoinContract.join(urn, _amt);
|
||||||
|
|
||||||
|
managerContract.frob(
|
||||||
|
_vault,
|
||||||
|
0,
|
||||||
|
_getWipeAmt(
|
||||||
|
vat,
|
||||||
|
VatLike(vat).dai(urn),
|
||||||
|
urn,
|
||||||
|
ilk,
|
||||||
|
_vault
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogPayback(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw leftover ETH/ERC20_Token after Liquidation.
|
||||||
|
* @notice Withdraw leftover collateral after Liquidation.
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt token amount to Withdraw. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of collateral withdrawn.
|
||||||
|
*/
|
||||||
|
function withdrawLiquidated(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(vault);
|
||||||
|
|
||||||
|
address colAddr = instaMapping.gemJoinMapping(ilk);
|
||||||
|
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
|
||||||
|
|
||||||
|
uint _amt18;
|
||||||
|
if (_amt == uint(-1)) {
|
||||||
|
_amt18 = VatLike(managerContract.vat()).gem(ilk, urn);
|
||||||
|
_amt = convert18ToDec(tokenJoinContract.dec(), _amt18);
|
||||||
|
} else {
|
||||||
|
_amt18 = convertTo18(tokenJoinContract.dec(), _amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
managerContract.flux(
|
||||||
|
vault,
|
||||||
|
address(this),
|
||||||
|
_amt18
|
||||||
|
);
|
||||||
|
|
||||||
|
TokenInterface tokenContract = tokenJoinContract.gem();
|
||||||
|
tokenJoinContract.exit(address(this), _amt);
|
||||||
|
if (isEth(address(tokenContract))) {
|
||||||
|
tokenContract.withdraw(_amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogWithdrawLiquidated(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MakerData {
|
||||||
|
uint _vault;
|
||||||
|
address colAddr;
|
||||||
|
TokenJoinInterface tokenJoinContract;
|
||||||
|
VatLike vatContract;
|
||||||
|
TokenInterface tokenContract;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @dev Deposit ETH/ERC20_Token Collateral and Borrow DAI.
|
||||||
|
* @notice Deposit collateral and borrow DAI.
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param depositAmt The amount of tokens to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param borrowAmt The amount of DAI to borrow.
|
||||||
|
* @param getIdDeposit ID to retrieve depositAmt.
|
||||||
|
* @param getIdBorrow ID to retrieve borrowAmt.
|
||||||
|
* @param setIdDeposit ID stores the amount of tokens deposited.
|
||||||
|
* @param setIdBorrow ID stores the amount of DAI borrowed.
|
||||||
|
*/
|
||||||
|
function depositAndBorrow(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 depositAmt,
|
||||||
|
uint256 borrowAmt,
|
||||||
|
uint256 getIdDeposit,
|
||||||
|
uint256 getIdBorrow,
|
||||||
|
uint256 setIdDeposit,
|
||||||
|
uint256 setIdBorrow
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
MakerData memory makerData;
|
||||||
|
uint _amtDeposit = getUint(getIdDeposit, depositAmt);
|
||||||
|
uint _amtBorrow = getUint(getIdBorrow, borrowAmt);
|
||||||
|
|
||||||
|
makerData._vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(makerData._vault);
|
||||||
|
|
||||||
|
makerData.colAddr = instaMapping.gemJoinMapping(ilk);
|
||||||
|
makerData.tokenJoinContract = TokenJoinInterface(makerData.colAddr);
|
||||||
|
makerData.vatContract = VatLike(managerContract.vat());
|
||||||
|
makerData.tokenContract = makerData.tokenJoinContract.gem();
|
||||||
|
|
||||||
|
if (isEth(address(makerData.tokenContract))) {
|
||||||
|
_amtDeposit = _amtDeposit == uint(-1) ? address(this).balance : _amtDeposit;
|
||||||
|
makerData.tokenContract.deposit{value: _amtDeposit}();
|
||||||
|
} else {
|
||||||
|
_amtDeposit = _amtDeposit == uint(-1) ? makerData.tokenContract.balanceOf(address(this)) : _amtDeposit;
|
||||||
|
}
|
||||||
|
|
||||||
|
approve(makerData.tokenContract, address(makerData.colAddr), _amtDeposit);
|
||||||
|
makerData.tokenJoinContract.join(urn, _amtDeposit);
|
||||||
|
|
||||||
|
managerContract.frob(
|
||||||
|
makerData._vault,
|
||||||
|
toInt(convertTo18(makerData.tokenJoinContract.dec(), _amtDeposit)),
|
||||||
|
_getBorrowAmt(
|
||||||
|
address(makerData.vatContract),
|
||||||
|
urn,
|
||||||
|
ilk,
|
||||||
|
_amtBorrow
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
managerContract.move(
|
||||||
|
makerData._vault,
|
||||||
|
address(this),
|
||||||
|
toRad(_amtBorrow)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (makerData.vatContract.can(address(this), address(daiJoinContract)) == 0) {
|
||||||
|
makerData.vatContract.hope(address(daiJoinContract));
|
||||||
|
}
|
||||||
|
|
||||||
|
daiJoinContract.exit(address(this), _amtBorrow);
|
||||||
|
|
||||||
|
setUint(setIdDeposit, _amtDeposit);
|
||||||
|
setUint(setIdBorrow, _amtBorrow);
|
||||||
|
|
||||||
|
_eventName = "LogDepositAndBorrow(uint256,bytes32,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
makerData._vault,
|
||||||
|
ilk,
|
||||||
|
_amtDeposit,
|
||||||
|
_amtBorrow,
|
||||||
|
getIdDeposit,
|
||||||
|
getIdBorrow,
|
||||||
|
setIdDeposit,
|
||||||
|
setIdBorrow
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Exit DAI from urn.
|
||||||
|
* @notice Exit DAI from urn.
|
||||||
|
* @param vault Vault ID. (Use 0 for last opened vault)
|
||||||
|
* @param amt The amount of DAI to exit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of DAI exited.
|
||||||
|
*/
|
||||||
|
function exitDai(
|
||||||
|
uint256 vault,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
uint _vault = getVault(vault);
|
||||||
|
(bytes32 ilk, address urn) = getVaultData(_vault);
|
||||||
|
|
||||||
|
VatLike vatContract = VatLike(managerContract.vat());
|
||||||
|
if(_amt == uint(-1)) {
|
||||||
|
_amt = vatContract.dai(urn);
|
||||||
|
_amt = _amt / 10 ** 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
managerContract.move(
|
||||||
|
_vault,
|
||||||
|
address(this),
|
||||||
|
toRad(_amt)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (vatContract.can(address(this), address(daiJoinContract)) == 0) {
|
||||||
|
vatContract.hope(address(daiJoinContract));
|
||||||
|
}
|
||||||
|
|
||||||
|
daiJoinContract.exit(address(this), _amt);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogExitDai(uint256,bytes32,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_vault, ilk, _amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit DAI in DSR.
|
||||||
|
* @notice Deposit DAI in DSR.
|
||||||
|
* @param amt The amount of DAI to deposit. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of DAI deposited.
|
||||||
|
*/
|
||||||
|
function depositDai(
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
_amt = _amt == uint(-1) ?
|
||||||
|
daiJoinContract.dai().balanceOf(address(this)) :
|
||||||
|
_amt;
|
||||||
|
|
||||||
|
VatLike vat = daiJoinContract.vat();
|
||||||
|
uint chi = potContract.drip();
|
||||||
|
|
||||||
|
approve(daiJoinContract.dai(), address(daiJoinContract), _amt);
|
||||||
|
daiJoinContract.join(address(this), _amt);
|
||||||
|
if (vat.can(address(this), address(potContract)) == 0) {
|
||||||
|
vat.hope(address(potContract));
|
||||||
|
}
|
||||||
|
|
||||||
|
potContract.join(mul(_amt, RAY) / chi);
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogDepositDai(uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_amt, getId, setId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw DAI from DSR.
|
||||||
|
* @notice Withdraw DAI from DSR.
|
||||||
|
* @param amt The amount of DAI to withdraw. (For max: `uint256(-1)`)
|
||||||
|
* @param getId ID to retrieve amt.
|
||||||
|
* @param setId ID stores the amount of DAI withdrawn.
|
||||||
|
*/
|
||||||
|
function withdrawDai(
|
||||||
|
uint256 amt,
|
||||||
|
uint256 getId,
|
||||||
|
uint256 setId
|
||||||
|
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
|
||||||
|
VatLike vat = daiJoinContract.vat();
|
||||||
|
|
||||||
|
uint chi = potContract.drip();
|
||||||
|
uint pie;
|
||||||
|
if (_amt == uint(-1)) {
|
||||||
|
pie = potContract.pie(address(this));
|
||||||
|
_amt = mul(chi, pie) / RAY;
|
||||||
|
} else {
|
||||||
|
pie = mul(_amt, RAY) / chi;
|
||||||
|
}
|
||||||
|
|
||||||
|
potContract.exit(pie);
|
||||||
|
|
||||||
|
uint bal = vat.dai(address(this));
|
||||||
|
if (vat.can(address(this), address(daiJoinContract)) == 0) {
|
||||||
|
vat.hope(address(daiJoinContract));
|
||||||
|
}
|
||||||
|
daiJoinContract.exit(
|
||||||
|
address(this),
|
||||||
|
bal >= mul(_amt, RAY) ? _amt : bal / RAY
|
||||||
|
);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
|
||||||
|
_eventName = "LogWithdrawDai(uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(_amt, getId, setId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectV2BMakerDAO is BMakerResolver {
|
||||||
|
string public constant name = "B.MakerDAO-v1.0";
|
||||||
|
}
|
34
contracts/mainnet/connectors/uniswapV3/events.sol
Normal file
34
contracts/mainnet/connectors/uniswapV3/events.sol
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
pragma solidity ^0.7.0;
|
||||||
|
|
||||||
|
contract Events {
|
||||||
|
event LogMint(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amtA,
|
||||||
|
uint256 amtB,
|
||||||
|
int24 tickLower,
|
||||||
|
int24 tickUpper
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogDeposit(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdraw(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogCollect(
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogBurnPosition(uint256 tokenId);
|
||||||
|
}
|
265
contracts/mainnet/connectors/uniswapV3/helpers.sol
Normal file
265
contracts/mainnet/connectors/uniswapV3/helpers.sol
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
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";
|
||||||
|
import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
|
||||||
|
import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
|
||||||
|
import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
|
||||||
|
|
||||||
|
abstract contract Helpers is DSMath, Basic {
|
||||||
|
/**
|
||||||
|
* @dev uniswap v3 NFT Position Manager & Swap Router
|
||||||
|
*/
|
||||||
|
INonfungiblePositionManager constant nftManager =
|
||||||
|
INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
|
||||||
|
ISwapRouter constant swapRouter =
|
||||||
|
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
|
||||||
|
|
||||||
|
struct MintParams {
|
||||||
|
address tokenA;
|
||||||
|
address tokenB;
|
||||||
|
uint24 fee;
|
||||||
|
int24 tickLower;
|
||||||
|
int24 tickUpper;
|
||||||
|
uint256 amtA;
|
||||||
|
uint256 amtB;
|
||||||
|
uint256 slippage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get Last NFT Index
|
||||||
|
* @param user: User address
|
||||||
|
*/
|
||||||
|
function _getLastNftId(address user)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (uint256 tokenId)
|
||||||
|
{
|
||||||
|
uint256 len = nftManager.balanceOf(user);
|
||||||
|
tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMinAmount(
|
||||||
|
TokenInterface token,
|
||||||
|
uint256 amt,
|
||||||
|
uint256 slippage
|
||||||
|
) internal view returns (uint256 minAmt) {
|
||||||
|
uint256 _amt18 = convertTo18(token.decimals(), amt);
|
||||||
|
minAmt = wmul(_amt18, sub(WAD, slippage));
|
||||||
|
minAmt = convert18ToDec(token.decimals(), minAmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Mint function which interact with Uniswap v3
|
||||||
|
*/
|
||||||
|
function _mint(MintParams memory params)
|
||||||
|
internal
|
||||||
|
returns (
|
||||||
|
uint256 tokenId,
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB
|
||||||
|
)
|
||||||
|
{
|
||||||
|
(TokenInterface _token0, TokenInterface _token1) = changeEthAddress(
|
||||||
|
params.tokenA,
|
||||||
|
params.tokenB
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 _amount0 = params.amtA == uint256(-1)
|
||||||
|
? getTokenBal(TokenInterface(params.tokenA))
|
||||||
|
: params.amtA;
|
||||||
|
uint256 _amount1 = params.amtB == uint256(-1)
|
||||||
|
? getTokenBal(TokenInterface(params.tokenB))
|
||||||
|
: params.amtB;
|
||||||
|
|
||||||
|
convertEthToWeth(address(_token0) == wethAddr, _token0, _amount0);
|
||||||
|
convertEthToWeth(address(_token1) == wethAddr, _token1, _amount1);
|
||||||
|
|
||||||
|
approve(_token0, address(nftManager), _amount0);
|
||||||
|
approve(_token1, address(nftManager), _amount1);
|
||||||
|
|
||||||
|
uint256 _minAmt0 = getMinAmount(_token0, _amount0, params.slippage);
|
||||||
|
uint256 _minAmt1 = getMinAmount(_token1, _amount1, params.slippage);
|
||||||
|
|
||||||
|
INonfungiblePositionManager.MintParams
|
||||||
|
memory params = INonfungiblePositionManager.MintParams(
|
||||||
|
address(_token0),
|
||||||
|
address(_token1),
|
||||||
|
params.fee,
|
||||||
|
params.tickLower,
|
||||||
|
params.tickUpper,
|
||||||
|
_amount0,
|
||||||
|
_amount1,
|
||||||
|
_minAmt0,
|
||||||
|
_minAmt1,
|
||||||
|
address(this),
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
(tokenId, liquidity, amountA, amountB) = nftManager.mint(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNftTokenPairAddresses(uint256 _tokenId)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (address token0, address token1)
|
||||||
|
{
|
||||||
|
(bool success, bytes memory data) = address(nftManager).staticcall(
|
||||||
|
abi.encodeWithSelector(nftManager.positions.selector, _tokenId)
|
||||||
|
);
|
||||||
|
require(success, "fetching positions failed");
|
||||||
|
{
|
||||||
|
(, , token0, token1, , , , ) = abi.decode(
|
||||||
|
data,
|
||||||
|
(
|
||||||
|
uint96,
|
||||||
|
address,
|
||||||
|
address,
|
||||||
|
address,
|
||||||
|
uint24,
|
||||||
|
int24,
|
||||||
|
int24,
|
||||||
|
uint128
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Check if token address is etherAddr and convert it to weth
|
||||||
|
*/
|
||||||
|
function _checkETH(
|
||||||
|
address _token0,
|
||||||
|
address _token1,
|
||||||
|
uint256 _amount0,
|
||||||
|
uint256 _amount1
|
||||||
|
) internal {
|
||||||
|
|
||||||
|
bool isEth0 = _token0 == wethAddr;
|
||||||
|
bool isEth1 = _token1 == wethAddr;
|
||||||
|
convertEthToWeth(isEth0, TokenInterface(_token0), _amount0);
|
||||||
|
convertEthToWeth(isEth1, TokenInterface(_token1), _amount1);
|
||||||
|
approve(TokenInterface(_token0), address(nftManager), _amount0);
|
||||||
|
approve(TokenInterface(_token1), address(nftManager), _amount1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev addLiquidityWrapper function wrapper of _addLiquidity
|
||||||
|
*/
|
||||||
|
function _addLiquidityWrapper(
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB,
|
||||||
|
uint256 slippage
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns (
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amtA,
|
||||||
|
uint256 amtB
|
||||||
|
)
|
||||||
|
{
|
||||||
|
(address token0, address token1) = getNftTokenPairAddresses(tokenId);
|
||||||
|
|
||||||
|
(liquidity, amtA, amtB) = _addLiquidity(
|
||||||
|
tokenId,
|
||||||
|
token0,
|
||||||
|
token1,
|
||||||
|
amountA,
|
||||||
|
amountB,
|
||||||
|
slippage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev addLiquidity function which interact with Uniswap v3
|
||||||
|
*/
|
||||||
|
function _addLiquidity(
|
||||||
|
uint256 _tokenId,
|
||||||
|
address _token0,
|
||||||
|
address _token1,
|
||||||
|
uint256 _amount0,
|
||||||
|
uint256 _amount1,
|
||||||
|
uint256 _slippage
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns (
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_checkETH(_token0, _token1, _amount0, _amount1);
|
||||||
|
uint256 _amount0Min = getMinAmount(
|
||||||
|
TokenInterface(_token0),
|
||||||
|
_amount0,
|
||||||
|
_slippage
|
||||||
|
);
|
||||||
|
uint256 _amount1Min = getMinAmount(
|
||||||
|
TokenInterface(_token1),
|
||||||
|
_amount1,
|
||||||
|
_slippage
|
||||||
|
);
|
||||||
|
INonfungiblePositionManager.IncreaseLiquidityParams
|
||||||
|
memory params = INonfungiblePositionManager.IncreaseLiquidityParams(
|
||||||
|
_tokenId,
|
||||||
|
_amount0,
|
||||||
|
_amount1,
|
||||||
|
_amount0Min,
|
||||||
|
_amount1Min,
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
(liquidity, amount0, amount1) = nftManager.increaseLiquidity(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev decreaseLiquidity function which interact with Uniswap v3
|
||||||
|
*/
|
||||||
|
function _decreaseLiquidity(
|
||||||
|
uint256 _tokenId,
|
||||||
|
uint128 _liquidity,
|
||||||
|
uint256 _amount0Min,
|
||||||
|
uint256 _amount1Min
|
||||||
|
) internal returns (uint256 amount0, uint256 amount1) {
|
||||||
|
INonfungiblePositionManager.DecreaseLiquidityParams
|
||||||
|
memory params = INonfungiblePositionManager.DecreaseLiquidityParams(
|
||||||
|
_tokenId,
|
||||||
|
_liquidity,
|
||||||
|
_amount0Min,
|
||||||
|
_amount1Min,
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
(amount0, amount1) = nftManager.decreaseLiquidity(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev collect function which interact with Uniswap v3
|
||||||
|
*/
|
||||||
|
function _collect(
|
||||||
|
uint256 _tokenId,
|
||||||
|
uint128 _amount0Max,
|
||||||
|
uint128 _amount1Max
|
||||||
|
) internal returns (uint256 amount0, uint256 amount1) {
|
||||||
|
INonfungiblePositionManager.CollectParams
|
||||||
|
memory params = INonfungiblePositionManager.CollectParams(
|
||||||
|
_tokenId,
|
||||||
|
address(this),
|
||||||
|
_amount0Max,
|
||||||
|
_amount1Max
|
||||||
|
);
|
||||||
|
(amount0, amount1) = nftManager.collect(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Burn Function
|
||||||
|
*/
|
||||||
|
function _burn(uint256 _tokenId) internal {
|
||||||
|
nftManager.burn(_tokenId);
|
||||||
|
}
|
||||||
|
}
|
368
contracts/mainnet/connectors/uniswapV3/interface.sol
Normal file
368
contracts/mainnet/connectors/uniswapV3/interface.sol
Normal file
|
@ -0,0 +1,368 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
pragma abicoder v2;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol";
|
||||||
|
|
||||||
|
/// @title Callback for IUniswapV3PoolActions#swap
|
||||||
|
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
|
||||||
|
interface IUniswapV3SwapCallback {
|
||||||
|
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
|
||||||
|
/// @dev In the implementation you must pay the pool tokens owed for the swap.
|
||||||
|
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
|
||||||
|
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
|
||||||
|
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
|
||||||
|
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
|
||||||
|
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
|
||||||
|
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
|
||||||
|
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
|
||||||
|
function uniswapV3SwapCallback(
|
||||||
|
int256 amount0Delta,
|
||||||
|
int256 amount1Delta,
|
||||||
|
bytes calldata data
|
||||||
|
) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISwapRouter is IUniswapV3SwapCallback {
|
||||||
|
struct ExactInputSingleParams {
|
||||||
|
address tokenIn;
|
||||||
|
address tokenOut;
|
||||||
|
uint24 fee;
|
||||||
|
address recipient;
|
||||||
|
uint256 deadline;
|
||||||
|
uint256 amountIn;
|
||||||
|
uint256 amountOutMinimum;
|
||||||
|
uint160 sqrtPriceLimitX96;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Swaps `amountIn` of one token for as much as possible of another token
|
||||||
|
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
|
||||||
|
/// @return amountOut The amount of the received token
|
||||||
|
function exactInputSingle(ExactInputSingleParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amountOut);
|
||||||
|
|
||||||
|
struct ExactInputParams {
|
||||||
|
bytes path;
|
||||||
|
address recipient;
|
||||||
|
uint256 deadline;
|
||||||
|
uint256 amountIn;
|
||||||
|
uint256 amountOutMinimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
|
||||||
|
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
|
||||||
|
/// @return amountOut The amount of the received token
|
||||||
|
function exactInput(ExactInputParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amountOut);
|
||||||
|
|
||||||
|
struct ExactOutputSingleParams {
|
||||||
|
address tokenIn;
|
||||||
|
address tokenOut;
|
||||||
|
uint24 fee;
|
||||||
|
address recipient;
|
||||||
|
uint256 deadline;
|
||||||
|
uint256 amountOut;
|
||||||
|
uint256 amountInMaximum;
|
||||||
|
uint160 sqrtPriceLimitX96;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Swaps as little as possible of one token for `amountOut` of another token
|
||||||
|
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
|
||||||
|
/// @return amountIn The amount of the input token
|
||||||
|
function exactOutputSingle(ExactOutputSingleParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amountIn);
|
||||||
|
|
||||||
|
struct ExactOutputParams {
|
||||||
|
bytes path;
|
||||||
|
address recipient;
|
||||||
|
uint256 deadline;
|
||||||
|
uint256 amountOut;
|
||||||
|
uint256 amountInMaximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
|
||||||
|
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
|
||||||
|
/// @return amountIn The amount of the input token
|
||||||
|
function exactOutput(ExactOutputParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amountIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @title Creates and initializes V3 Pools
|
||||||
|
/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that
|
||||||
|
/// require the pool to exist.
|
||||||
|
interface IPoolInitializer {
|
||||||
|
/// @notice Creates a new pool if it does not exist, then initializes if not initialized
|
||||||
|
/// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool
|
||||||
|
/// @param token0 The contract address of token0 of the pool
|
||||||
|
/// @param token1 The contract address of token1 of the pool
|
||||||
|
/// @param fee The fee amount of the v3 pool for the specified token pair
|
||||||
|
/// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value
|
||||||
|
/// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary
|
||||||
|
function createAndInitializePoolIfNecessary(
|
||||||
|
address token0,
|
||||||
|
address token1,
|
||||||
|
uint24 fee,
|
||||||
|
uint160 sqrtPriceX96
|
||||||
|
) external payable returns (address pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @title Immutable state
|
||||||
|
/// @notice Functions that return immutable state of the router
|
||||||
|
interface IPeripheryImmutableState {
|
||||||
|
/// @return Returns the address of the Uniswap V3 factory
|
||||||
|
function factory() external view returns (address);
|
||||||
|
|
||||||
|
/// @return Returns the address of WETH9
|
||||||
|
function WETH9() external view returns (address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @title Periphery Payments
|
||||||
|
/// @notice Functions to ease deposits and withdrawals of ETH
|
||||||
|
interface IPeripheryPayments {
|
||||||
|
/// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.
|
||||||
|
/// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.
|
||||||
|
/// @param amountMinimum The minimum amount of WETH9 to unwrap
|
||||||
|
/// @param recipient The address receiving ETH
|
||||||
|
function unwrapWETH9(uint256 amountMinimum, address recipient)
|
||||||
|
external
|
||||||
|
payable;
|
||||||
|
|
||||||
|
/// @notice Refunds any ETH balance held by this contract to the `msg.sender`
|
||||||
|
/// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps
|
||||||
|
/// that use ether for the input amount
|
||||||
|
function refundETH() external payable;
|
||||||
|
|
||||||
|
/// @notice Transfers the full amount of a token held by this contract to recipient
|
||||||
|
/// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users
|
||||||
|
/// @param token The contract address of the token which will be transferred to `recipient`
|
||||||
|
/// @param amountMinimum The minimum amount of token required for a transfer
|
||||||
|
/// @param recipient The destination address of the token
|
||||||
|
function sweepToken(
|
||||||
|
address token,
|
||||||
|
uint256 amountMinimum,
|
||||||
|
address recipient
|
||||||
|
) external payable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @title ERC721 with permit
|
||||||
|
/// @notice Extension to ERC721 that includes a permit function for signature based approvals
|
||||||
|
interface IERC721Permit is IERC721 {
|
||||||
|
/// @notice The permit typehash used in the permit signature
|
||||||
|
/// @return The typehash for the permit
|
||||||
|
function PERMIT_TYPEHASH() external pure returns (bytes32);
|
||||||
|
|
||||||
|
/// @notice The domain separator used in the permit signature
|
||||||
|
/// @return The domain seperator used in encoding of permit signature
|
||||||
|
function DOMAIN_SEPARATOR() external view returns (bytes32);
|
||||||
|
|
||||||
|
/// @notice Approve of a specific token ID for spending by spender via signature
|
||||||
|
/// @param spender The account that is being approved
|
||||||
|
/// @param tokenId The ID of the token that is being approved for spending
|
||||||
|
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
|
||||||
|
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
|
||||||
|
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
|
||||||
|
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
|
||||||
|
function permit(
|
||||||
|
address spender,
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 deadline,
|
||||||
|
uint8 v,
|
||||||
|
bytes32 r,
|
||||||
|
bytes32 s
|
||||||
|
) external payable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @title Non-fungible token for positions
|
||||||
|
/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred
|
||||||
|
/// and authorized.
|
||||||
|
interface INonfungiblePositionManager is
|
||||||
|
IPoolInitializer,
|
||||||
|
IPeripheryPayments,
|
||||||
|
IPeripheryImmutableState,
|
||||||
|
IERC721Metadata,
|
||||||
|
IERC721Enumerable,
|
||||||
|
IERC721Permit
|
||||||
|
{
|
||||||
|
/// @notice Emitted when liquidity is increased for a position NFT
|
||||||
|
/// @dev Also emitted when a token is minted
|
||||||
|
/// @param tokenId The ID of the token for which liquidity was increased
|
||||||
|
/// @param liquidity The amount by which liquidity for the NFT position was increased
|
||||||
|
/// @param amount0 The amount of token0 that was paid for the increase in liquidity
|
||||||
|
/// @param amount1 The amount of token1 that was paid for the increase in liquidity
|
||||||
|
event IncreaseLiquidity(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
);
|
||||||
|
/// @notice Emitted when liquidity is decreased for a position NFT
|
||||||
|
/// @param tokenId The ID of the token for which liquidity was decreased
|
||||||
|
/// @param liquidity The amount by which liquidity for the NFT position was decreased
|
||||||
|
/// @param amount0 The amount of token0 that was accounted for the decrease in liquidity
|
||||||
|
/// @param amount1 The amount of token1 that was accounted for the decrease in liquidity
|
||||||
|
event DecreaseLiquidity(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
);
|
||||||
|
/// @notice Emitted when tokens are collected for a position NFT
|
||||||
|
/// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior
|
||||||
|
/// @param tokenId The ID of the token for which underlying tokens were collected
|
||||||
|
/// @param recipient The address of the account that received the collected tokens
|
||||||
|
/// @param amount0 The amount of token0 owed to the position that was collected
|
||||||
|
/// @param amount1 The amount of token1 owed to the position that was collected
|
||||||
|
event Collect(
|
||||||
|
uint256 indexed tokenId,
|
||||||
|
address recipient,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @notice Returns the position information associated with a given token ID.
|
||||||
|
/// @dev Throws if the token ID is not valid.
|
||||||
|
/// @param tokenId The ID of the token that represents the position
|
||||||
|
/// @return nonce The nonce for permits
|
||||||
|
/// @return operator The address that is approved for spending
|
||||||
|
/// @return token0 The address of the token0 for a specific pool
|
||||||
|
/// @return token1 The address of the token1 for a specific pool
|
||||||
|
/// @return fee The fee associated with the pool
|
||||||
|
/// @return tickLower The lower end of the tick range for the position
|
||||||
|
/// @return tickUpper The higher end of the tick range for the position
|
||||||
|
/// @return liquidity The liquidity of the position
|
||||||
|
/// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position
|
||||||
|
/// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position
|
||||||
|
/// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation
|
||||||
|
/// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation
|
||||||
|
function positions(uint256 tokenId)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (
|
||||||
|
uint96 nonce,
|
||||||
|
address operator,
|
||||||
|
address token0,
|
||||||
|
address token1,
|
||||||
|
uint24 fee,
|
||||||
|
int24 tickLower,
|
||||||
|
int24 tickUpper,
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 feeGrowthInside0LastX128,
|
||||||
|
uint256 feeGrowthInside1LastX128,
|
||||||
|
uint128 tokensOwed0,
|
||||||
|
uint128 tokensOwed1
|
||||||
|
);
|
||||||
|
|
||||||
|
struct MintParams {
|
||||||
|
address token0;
|
||||||
|
address token1;
|
||||||
|
uint24 fee;
|
||||||
|
int24 tickLower;
|
||||||
|
int24 tickUpper;
|
||||||
|
uint256 amount0Desired;
|
||||||
|
uint256 amount1Desired;
|
||||||
|
uint256 amount0Min;
|
||||||
|
uint256 amount1Min;
|
||||||
|
address recipient;
|
||||||
|
uint256 deadline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Creates a new position wrapped in a NFT
|
||||||
|
/// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized
|
||||||
|
/// a method does not exist, i.e. the pool is assumed to be initialized.
|
||||||
|
/// @param params The params necessary to mint a position, encoded as `MintParams` in calldata
|
||||||
|
/// @return tokenId The ID of the token that represents the minted position
|
||||||
|
/// @return liquidity The amount of liquidity for this position
|
||||||
|
/// @return amount0 The amount of token0
|
||||||
|
/// @return amount1 The amount of token1
|
||||||
|
function mint(MintParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (
|
||||||
|
uint256 tokenId,
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
);
|
||||||
|
|
||||||
|
struct IncreaseLiquidityParams {
|
||||||
|
uint256 tokenId;
|
||||||
|
uint256 amount0Desired;
|
||||||
|
uint256 amount1Desired;
|
||||||
|
uint256 amount0Min;
|
||||||
|
uint256 amount1Min;
|
||||||
|
uint256 deadline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`
|
||||||
|
/// @param params tokenId The ID of the token for which liquidity is being increased,
|
||||||
|
/// amount0Desired The desired amount of token0 to be spent,
|
||||||
|
/// amount1Desired The desired amount of token1 to be spent,
|
||||||
|
/// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,
|
||||||
|
/// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,
|
||||||
|
/// deadline The time by which the transaction must be included to effect the change
|
||||||
|
/// @return liquidity The new liquidity amount as a result of the increase
|
||||||
|
/// @return amount0 The amount of token0 to acheive resulting liquidity
|
||||||
|
/// @return amount1 The amount of token1 to acheive resulting liquidity
|
||||||
|
function increaseLiquidity(IncreaseLiquidityParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (
|
||||||
|
uint128 liquidity,
|
||||||
|
uint256 amount0,
|
||||||
|
uint256 amount1
|
||||||
|
);
|
||||||
|
|
||||||
|
struct DecreaseLiquidityParams {
|
||||||
|
uint256 tokenId;
|
||||||
|
uint128 liquidity;
|
||||||
|
uint256 amount0Min;
|
||||||
|
uint256 amount1Min;
|
||||||
|
uint256 deadline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Decreases the amount of liquidity in a position and accounts it to the position
|
||||||
|
/// @param params tokenId The ID of the token for which liquidity is being decreased,
|
||||||
|
/// amount The amount by which liquidity will be decreased,
|
||||||
|
/// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,
|
||||||
|
/// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,
|
||||||
|
/// deadline The time by which the transaction must be included to effect the change
|
||||||
|
/// @return amount0 The amount of token0 accounted to the position's tokens owed
|
||||||
|
/// @return amount1 The amount of token1 accounted to the position's tokens owed
|
||||||
|
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amount0, uint256 amount1);
|
||||||
|
|
||||||
|
struct CollectParams {
|
||||||
|
uint256 tokenId;
|
||||||
|
address recipient;
|
||||||
|
uint128 amount0Max;
|
||||||
|
uint128 amount1Max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient
|
||||||
|
/// @param params tokenId The ID of the NFT for which tokens are being collected,
|
||||||
|
/// recipient The account that should receive the tokens,
|
||||||
|
/// amount0Max The maximum amount of token0 to collect,
|
||||||
|
/// amount1Max The maximum amount of token1 to collect
|
||||||
|
/// @return amount0 The amount of fees collected in token0
|
||||||
|
/// @return amount1 The amount of fees collected in token1
|
||||||
|
function collect(CollectParams calldata params)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 amount0, uint256 amount1);
|
||||||
|
|
||||||
|
/// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens
|
||||||
|
/// must be collected first.
|
||||||
|
/// @param tokenId The ID of the token that is being burned
|
||||||
|
function burn(uint256 tokenId) external payable;
|
||||||
|
}
|
210
contracts/mainnet/connectors/uniswapV3/main.sol
Normal file
210
contracts/mainnet/connectors/uniswapV3/main.sol
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
pragma solidity ^0.7.6;
|
||||||
|
pragma abicoder v2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Uniswap v3.
|
||||||
|
* @dev Decentralized Exchange.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {TokenInterface} from "../../common/interfaces.sol";
|
||||||
|
import {Helpers} from "./helpers.sol";
|
||||||
|
import {Events} from "./events.sol";
|
||||||
|
|
||||||
|
abstract contract UniswapResolver is Helpers, Events {
|
||||||
|
/**
|
||||||
|
* @dev Mint New Position
|
||||||
|
* @notice Mint New NFT LP Position
|
||||||
|
* @param tokenA tokenA addreess
|
||||||
|
* @param tokenB tokenB addreess
|
||||||
|
* @param fee fee percentage
|
||||||
|
* @param tickLower Lower tick
|
||||||
|
* @param tickUpper Upper tick
|
||||||
|
* @param amtA amount of tokenA
|
||||||
|
* @param amtB amount of tokenB
|
||||||
|
* @param slippage slippage percentage
|
||||||
|
* @param getIds ID to retrieve amtA
|
||||||
|
* @param setId ID stores the amount of LP token
|
||||||
|
*/
|
||||||
|
function mint(
|
||||||
|
address tokenA,
|
||||||
|
address tokenB,
|
||||||
|
uint24 fee,
|
||||||
|
int24 tickLower,
|
||||||
|
int24 tickUpper,
|
||||||
|
uint256 amtA,
|
||||||
|
uint256 amtB,
|
||||||
|
uint256 slippage,
|
||||||
|
uint256[] calldata getIds,
|
||||||
|
uint256 setId
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
MintParams memory params;
|
||||||
|
{
|
||||||
|
params = MintParams(
|
||||||
|
tokenA,
|
||||||
|
tokenB,
|
||||||
|
fee,
|
||||||
|
tickLower,
|
||||||
|
tickUpper,
|
||||||
|
amtA,
|
||||||
|
amtB,
|
||||||
|
slippage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
params.amtA = getUint(getIds[0], params.amtA);
|
||||||
|
params.amtB = getUint(getIds[1], params.amtB);
|
||||||
|
|
||||||
|
(
|
||||||
|
uint256 _tokenId,
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB
|
||||||
|
) = _mint(params);
|
||||||
|
|
||||||
|
setUint(setId, liquidity);
|
||||||
|
|
||||||
|
_eventName = "LogMint(uint256,uint256,uint256,uint256,int24,int24)";
|
||||||
|
_eventParam = abi.encode(
|
||||||
|
_tokenId,
|
||||||
|
liquidity,
|
||||||
|
amountA,
|
||||||
|
amountB,
|
||||||
|
params.tickLower,
|
||||||
|
params.tickUpper
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Increase Liquidity
|
||||||
|
* @notice Increase Liquidity of NFT Position
|
||||||
|
* @param tokenId NFT LP Token ID.
|
||||||
|
* @param amountA tokenA amounts.
|
||||||
|
* @param amountB tokenB amounts.
|
||||||
|
* @param slippage slippage.
|
||||||
|
* @param getIds IDs to retrieve token amounts
|
||||||
|
* @param setId stores the liquidity amount
|
||||||
|
*/
|
||||||
|
function deposit(
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 amountA,
|
||||||
|
uint256 amountB,
|
||||||
|
uint256 slippage,
|
||||||
|
uint256[] calldata getIds,
|
||||||
|
uint256 setId
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
if (tokenId == 0) tokenId = _getLastNftId(address(this));
|
||||||
|
amountA = getUint(getIds[0], amountA);
|
||||||
|
amountB = getUint(getIds[1], amountB);
|
||||||
|
(
|
||||||
|
uint256 _liquidity,
|
||||||
|
uint256 _amtA,
|
||||||
|
uint256 _amtB
|
||||||
|
) = _addLiquidityWrapper(tokenId, amountA, amountB, slippage);
|
||||||
|
setUint(setId, _liquidity);
|
||||||
|
|
||||||
|
_eventName = "LogDeposit(uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Decrease Liquidity
|
||||||
|
* @notice Decrease Liquidity of NFT Position
|
||||||
|
* @param tokenId NFT LP Token ID.
|
||||||
|
* @param liquidity LP Token amount.
|
||||||
|
* @param amountAMin Min amount of tokenA.
|
||||||
|
* @param amountBMin Min amount of tokenB.
|
||||||
|
* @param getId ID to retrieve LP token amounts
|
||||||
|
* @param setIds stores the amount of output tokens
|
||||||
|
*/
|
||||||
|
function withdraw(
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 liquidity,
|
||||||
|
uint256 amountAMin,
|
||||||
|
uint256 amountBMin,
|
||||||
|
uint256 getId,
|
||||||
|
uint256[] calldata setIds
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
if (tokenId == 0) tokenId = _getLastNftId(address(this));
|
||||||
|
uint128 _liquidity = uint128(getUint(getId, liquidity));
|
||||||
|
|
||||||
|
(uint256 _amtA, uint256 _amtB) = _decreaseLiquidity(
|
||||||
|
tokenId,
|
||||||
|
_liquidity,
|
||||||
|
amountAMin,
|
||||||
|
amountBMin
|
||||||
|
);
|
||||||
|
|
||||||
|
setUint(setIds[0], _amtA);
|
||||||
|
setUint(setIds[1], _amtB);
|
||||||
|
|
||||||
|
_eventName = "LogWithdraw(uint256,uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Collect function
|
||||||
|
* @notice Collect from NFT Position
|
||||||
|
* @param tokenId NFT LP Token ID.
|
||||||
|
* @param amount0Max Max amount of token0.
|
||||||
|
* @param amount1Max Max amount of token1.
|
||||||
|
* @param getIds IDs to retrieve amounts
|
||||||
|
* @param setIds stores the amount of output tokens
|
||||||
|
*/
|
||||||
|
function collect(
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 amount0Max,
|
||||||
|
uint256 amount1Max,
|
||||||
|
uint256[] calldata getIds,
|
||||||
|
uint256[] calldata setIds
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
if (tokenId == 0) tokenId = _getLastNftId(address(this));
|
||||||
|
uint128 _amount0Max = uint128(getUint(getIds[0], amount0Max));
|
||||||
|
uint128 _amount1Max = uint128(getUint(getIds[1], amount1Max));
|
||||||
|
(uint256 amount0, uint256 amount1) = _collect(
|
||||||
|
tokenId,
|
||||||
|
_amount0Max,
|
||||||
|
_amount1Max
|
||||||
|
);
|
||||||
|
|
||||||
|
setUint(setIds[0], amount0);
|
||||||
|
setUint(setIds[1], amount1);
|
||||||
|
_eventName = "LogCollect(uint256,uint256,uint256)";
|
||||||
|
_eventParam = abi.encode(tokenId, amount0, amount1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Burn Function
|
||||||
|
* @notice Burn NFT LP Position
|
||||||
|
* @param tokenId NFT LP Token ID
|
||||||
|
*/
|
||||||
|
function burn(uint256 tokenId)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (string memory _eventName, bytes memory _eventParam)
|
||||||
|
{
|
||||||
|
if (tokenId == 0) tokenId = _getLastNftId(address(this));
|
||||||
|
_burn(tokenId);
|
||||||
|
_eventName = "LogBurnPosition(uint256)";
|
||||||
|
_eventParam = abi.encode(tokenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectV2UniswapV3 is UniswapResolver {
|
||||||
|
string public constant name = "UniswapV3-v1";
|
||||||
|
}
|
|
@ -25,7 +25,11 @@
|
||||||
"REFINANCE-A": "0x6f22931423e8ffC8d51f6E5aF73118fC64b27856",
|
"REFINANCE-A": "0x6f22931423e8ffC8d51f6E5aF73118fC64b27856",
|
||||||
"INST-A": "0x52C2C4a0db049255fF345EB9D3Fb1f555b7a924A",
|
"INST-A": "0x52C2C4a0db049255fF345EB9D3Fb1f555b7a924A",
|
||||||
"REFLEXER-A": "0xaC6dc28a6251F49Bbe5755E630107Dccde9ae2C8",
|
"REFLEXER-A": "0xaC6dc28a6251F49Bbe5755E630107Dccde9ae2C8",
|
||||||
"LIQUITY-A": "0x3643bA40B8e2bd8F77233BDB6abe38c218f31bFe"
|
"LIQUITY-A": "0x3643bA40B8e2bd8F77233BDB6abe38c218f31bFe",
|
||||||
|
"UNISWAP-V3-A": "0x25B0c76dE86C3457b9B8b9ee3775F5a7b8D4c475",
|
||||||
|
"B-COMPOUND-A": "0xa3EeFDc2de9DFA59968bEcff3E15b53E6162460f",
|
||||||
|
"B-MAKERDAO-A": "0xB0A1f10FeEfECf25064CE7cdF0a65042F7dE7bF0",
|
||||||
|
"B-LIQUITY-A": "0x19574E5Dfb40bbD63A4F3bdcF27ed662b329b2ff"
|
||||||
},
|
},
|
||||||
"137" : {
|
"137" : {
|
||||||
"1INCH-A": "0xC0d9210496afE9763F5d8cEb8deFfBa817232A9e",
|
"1INCH-A": "0xC0d9210496afE9763F5d8cEb8deFfBa817232A9e",
|
||||||
|
|
|
@ -57,9 +57,10 @@ module.exports = {
|
||||||
hardhat: {
|
hardhat: {
|
||||||
forking: {
|
forking: {
|
||||||
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
|
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
|
||||||
blockNumber: 12970000,
|
blockNumber: 13005785,
|
||||||
},
|
},
|
||||||
blockGasLimit: 12000000,
|
blockGasLimit: 12000000,
|
||||||
|
gasPrice: parseInt(utils.parseUnits("300", "gwei"))
|
||||||
},
|
},
|
||||||
matic: {
|
matic: {
|
||||||
url: "https://rpc-mainnet.maticvigil.com/",
|
url: "https://rpc-mainnet.maticvigil.com/",
|
||||||
|
|
20335
package-lock.json
generated
20335
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
|
@ -7,8 +7,7 @@
|
||||||
"test": "hardhat test",
|
"test": "hardhat test",
|
||||||
"coverage": "./node_modules/.bin/solidity-coverage",
|
"coverage": "./node_modules/.bin/solidity-coverage",
|
||||||
"check-husky": "node status-checks/huskyCheck.js",
|
"check-husky": "node status-checks/huskyCheck.js",
|
||||||
"build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build",
|
"build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build"
|
||||||
"prepare": "husky install"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -22,6 +21,8 @@
|
||||||
"homepage": "https://github.com/InstaDApp/dsa-connectors-new#readme",
|
"homepage": "https://github.com/InstaDApp/dsa-connectors-new#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openzeppelin/contracts": "^3.4.0-solc-0.7",
|
"@openzeppelin/contracts": "^3.4.0-solc-0.7",
|
||||||
|
"@uniswap/v3-core": "^1.0.0",
|
||||||
|
"@uniswap/v3-periphery": "^1.1.1",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
"commander": "^7.1.0",
|
"commander": "^7.1.0",
|
||||||
"dotenv": "^7.0.0",
|
"dotenv": "^7.0.0",
|
||||||
|
@ -31,21 +32,21 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
"@nomiclabs/hardhat-etherscan": "^2.1.3",
|
"@nomiclabs/hardhat-etherscan": "^2.1.4",
|
||||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||||
"@nomiclabs/hardhat-web3": "^2.0.0",
|
"@nomiclabs/hardhat-web3": "^2.0.0",
|
||||||
"@openzeppelin/test-helpers": "^0.5.6",
|
"@openzeppelin/test-helpers": "^0.5.12",
|
||||||
"@studydefi/money-legos": "^2.3.7",
|
"@studydefi/money-legos": "^2.3.7",
|
||||||
"@tenderly/hardhat-tenderly": "^1.0.6",
|
"@tenderly/hardhat-tenderly": "^1.0.12",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"ethereum-waffle": "^3.3.0",
|
"ethereum-waffle": "^3.4.0",
|
||||||
"ethers": "^5.1.4",
|
"ethers": "^5.4.4",
|
||||||
"hardhat": "^2.3.0",
|
"hardhat": "^2.6.0",
|
||||||
"hardhat-deploy": "^0.7.5",
|
"hardhat-deploy": "^0.8.11",
|
||||||
"hardhat-deploy-ethers": "^0.3.0-beta.7",
|
"hardhat-deploy-ethers": "^0.3.0-beta.10",
|
||||||
"husky": "^6.0.0",
|
"husky": "^6.0.0",
|
||||||
"sol-merger": "^2.0.1",
|
"sol-merger": "^2.0.1",
|
||||||
"solidity-coverage": "0.5.11",
|
"solidity-coverage": "0.5.11",
|
||||||
"web3": "^1.3.0"
|
"web3": "^1.3.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
128
test/b.protocol/b.compound.test.js
Normal file
128
test/b.protocol/b.compound.test.js
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const hre = require("hardhat");
|
||||||
|
const { web3, deployments, waffle, ethers } = hre;
|
||||||
|
const { provider, deployContract } = waffle
|
||||||
|
|
||||||
|
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
|
||||||
|
const buildDSAv2 = require("../../scripts/buildDSAv2")
|
||||||
|
const encodeSpells = require("../../scripts/encodeSpells.js")
|
||||||
|
const getMasterSigner = require("../../scripts/getMasterSigner")
|
||||||
|
|
||||||
|
const addresses = require("../../scripts/constant/addresses");
|
||||||
|
const abis = require("../../scripts/constant/abis");
|
||||||
|
const constants = require("../../scripts/constant/constant");
|
||||||
|
const tokens = require("../../scripts/constant/tokens");
|
||||||
|
|
||||||
|
const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/compound/main.sol/ConnectV1BCompound.json")
|
||||||
|
|
||||||
|
describe("B.Compound", function () {
|
||||||
|
const connectorName = "B.COMPOUND-TEST-A"
|
||||||
|
|
||||||
|
let dsaWallet0
|
||||||
|
let masterSigner;
|
||||||
|
let instaConnectorsV2;
|
||||||
|
let connector;
|
||||||
|
|
||||||
|
const wallets = provider.getWallets()
|
||||||
|
const [wallet0, wallet1, wallet2, wallet3] = wallets
|
||||||
|
before(async () => {
|
||||||
|
masterSigner = await getMasterSigner(wallet3)
|
||||||
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||||
|
connector = await deployAndEnableConnector({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact: connectV2CompoundArtifacts,
|
||||||
|
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(!!masterSigner.address).to.be.true;
|
||||||
|
expect(await connector.name()).to.be.equal("B.Compound-v1.0");
|
||||||
|
});
|
||||||
|
|
||||||
|
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 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"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Main", function () {
|
||||||
|
|
||||||
|
it("Should deposit ETH in Compound", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("1") // 1 ETH
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: ["ETH-A", amount, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should borrow and payback DAI from Compound", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("100") // 100 DAI
|
||||||
|
const setId = "83478237"
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "borrow",
|
||||||
|
args: ["DAI-A", amount, 0, setId]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "payback",
|
||||||
|
args: ["DAI-A", 0, setId, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should deposit all ETH in Compound", async function () {
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: ["ETH-A", constants.max_value, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("0"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should withdraw all ETH from Compound", async function () {
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "withdraw",
|
||||||
|
args: ["ETH-A", constants.max_value, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
181
test/b.protocol/b.liquity.test.js
Normal file
181
test/b.protocol/b.liquity.test.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const hre = require("hardhat");
|
||||||
|
const { web3, deployments, waffle, ethers } = hre;
|
||||||
|
const { provider, deployContract } = waffle
|
||||||
|
|
||||||
|
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
|
||||||
|
const buildDSAv2 = require("../../scripts/buildDSAv2")
|
||||||
|
const encodeSpells = require("../../scripts/encodeSpells.js")
|
||||||
|
const getMasterSigner = require("../../scripts/getMasterSigner")
|
||||||
|
|
||||||
|
const addresses = require("../../scripts/constant/addresses");
|
||||||
|
const abis = require("../../scripts/constant/abis");
|
||||||
|
const constants = require("../../scripts/constant/constant");
|
||||||
|
const tokens = require("../../scripts/constant/tokens");
|
||||||
|
|
||||||
|
const connectorLiquityArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/liquity/main.sol/ConnectV2BLiquity.json")
|
||||||
|
|
||||||
|
const LUSD_WHALE = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb" // stability pool
|
||||||
|
|
||||||
|
const BAMM_ADDRESS = "0x0d3AbAA7E088C2c82f54B2f47613DA438ea8C598"
|
||||||
|
|
||||||
|
describe("B.Liquity", function () {
|
||||||
|
const connectorName = "B.LIQUITY-TEST-A"
|
||||||
|
|
||||||
|
let dsaWallet0;
|
||||||
|
let dsaWallet1;
|
||||||
|
let masterSigner;
|
||||||
|
let instaConnectorsV2;
|
||||||
|
let connector;
|
||||||
|
let manager;
|
||||||
|
let vat;
|
||||||
|
let lusd;
|
||||||
|
let bammToken;
|
||||||
|
let stabilityPool;
|
||||||
|
|
||||||
|
const wallets = provider.getWallets()
|
||||||
|
const [wallet0, wallet1, wallet2, wallet3] = wallets
|
||||||
|
before(async () => {
|
||||||
|
masterSigner = await getMasterSigner(wallet3)
|
||||||
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||||
|
connector = await deployAndEnableConnector({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact: connectorLiquityArtifacts,
|
||||||
|
signer: masterSigner,
|
||||||
|
connectors: instaConnectorsV2
|
||||||
|
})
|
||||||
|
|
||||||
|
lusd = await ethers.getContractAt("../artifacts/contracts/mainnet/common/interfaces.sol:TokenInterface", "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0")
|
||||||
|
bammToken = await ethers.getContractAt("../artifacts/contracts/mainnet/connectors/b.protocol/liquity/interface.sol:BAMMLike", BAMM_ADDRESS)
|
||||||
|
stabilityPool = await ethers.getContractAt("../artifacts/contracts/mainnet/connectors/b.protocol/liquity/interface.sol:StabilityPoolLike", "0x66017D22b0f8556afDd19FC67041899Eb65a21bb")
|
||||||
|
|
||||||
|
console.log("Connector address", connector.address)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("test veryClose.", async function () {
|
||||||
|
expect(veryClose(1000001, 1000000)).to.be.true
|
||||||
|
expect(veryClose(1000000, 1000001)).to.be.true
|
||||||
|
expect(veryClose(1003000, 1000001)).to.be.false
|
||||||
|
expect(veryClose(1000001, 1000300)).to.be.false
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should have contracts deployed.", async function () {
|
||||||
|
expect(!!instaConnectorsV2.address).to.be.true;
|
||||||
|
expect(!!connector.address).to.be.true;
|
||||||
|
expect(!!masterSigner.address).to.be.true;
|
||||||
|
expect(await connector.name()).to.be.equal("B.Liquity-v1");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("DSA wallet setup", function () {
|
||||||
|
it("Should build DSA v2", async function () {
|
||||||
|
dsaWallet0 = await buildDSAv2(wallet0.address)
|
||||||
|
expect(!!dsaWallet0.address).to.be.true;
|
||||||
|
|
||||||
|
dsaWallet1 = await buildDSAv2(wallet1.address)
|
||||||
|
expect(!!dsaWallet1.address).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Deposit LUSD into DSA wallet", async function () {
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [LUSD_WHALE],
|
||||||
|
});
|
||||||
|
|
||||||
|
const signer = await hre.ethers.provider.getSigner(LUSD_WHALE);
|
||||||
|
await lusd.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("100000"))
|
||||||
|
|
||||||
|
expect(await lusd.balanceOf(dsaWallet0.address)).to.equal(ethers.utils.parseEther("100000"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Main", function () {
|
||||||
|
it("should deposit 10k LUSD", async function () {
|
||||||
|
const totalSupplyBefore = await bammToken.totalSupply();
|
||||||
|
const lusdBalanceBefore = await stabilityPool.getCompoundedLUSDDeposit(BAMM_ADDRESS);
|
||||||
|
const amount = ethers.utils.parseEther("10000");
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [amount, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
const expectedBalance = totalSupplyBefore.mul(amount).div(lusdBalanceBefore)
|
||||||
|
expect(veryClose(expectedBalance, await bammToken.balanceOf(dsaWallet0.address))).to.be.true
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should deposit all LUSD", async function () {
|
||||||
|
const totalSupplyBefore = await bammToken.totalSupply();
|
||||||
|
const lusdBalanceBefore = await stabilityPool.getCompoundedLUSDDeposit(BAMM_ADDRESS);
|
||||||
|
const amount = web3.utils.toBN("2").pow(web3.utils.toBN("256")).sub(web3.utils.toBN("1"));
|
||||||
|
const balanceBefore = await bammToken.balanceOf(dsaWallet0.address)
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [amount, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
const expectedBalance = (totalSupplyBefore.mul(ethers.utils.parseEther("90000")).div(lusdBalanceBefore)).add(balanceBefore)
|
||||||
|
expect(veryClose(expectedBalance, await bammToken.balanceOf(dsaWallet0.address))).to.be.true
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should withdraw half of the shares", async function () {
|
||||||
|
const balanceBefore = await bammToken.balanceOf(dsaWallet0.address)
|
||||||
|
const halfBalance = balanceBefore.div("2")
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "withdraw",
|
||||||
|
args: [halfBalance, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(veryClose(halfBalance, await bammToken.balanceOf(dsaWallet0.address))).to.be.true
|
||||||
|
expect(veryClose(ethers.utils.parseEther("50000"), await lusd.balanceOf(dsaWallet0.address))).to.be.true
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should withdraw all the shares", async function () {
|
||||||
|
const amount = web3.utils.toBN("2").pow(web3.utils.toBN("256")).sub(web3.utils.toBN("1"));
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "withdraw",
|
||||||
|
args: [amount, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(veryClose(ethers.utils.parseEther("100000"), await lusd.balanceOf(dsaWallet0.address))).to.be.true
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function veryClose(n1, n2) {
|
||||||
|
n1 = web3.utils.toBN(n1)
|
||||||
|
n2 = web3.utils.toBN(n2)
|
||||||
|
|
||||||
|
_10000 = web3.utils.toBN(10000)
|
||||||
|
_9999 = web3.utils.toBN(9999)
|
||||||
|
|
||||||
|
if(n1.mul(_10000).lt(n2.mul(_9999))) return false
|
||||||
|
if(n2.mul(_10000).lt(n1.mul(_9999))) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
326
test/b.protocol/b.maker.test.js
Normal file
326
test/b.protocol/b.maker.test.js
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const hre = require("hardhat");
|
||||||
|
const { web3, deployments, waffle, ethers } = hre;
|
||||||
|
const { provider, deployContract } = waffle
|
||||||
|
|
||||||
|
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
|
||||||
|
const buildDSAv2 = require("../../scripts/buildDSAv2")
|
||||||
|
const encodeSpells = require("../../scripts/encodeSpells.js")
|
||||||
|
const getMasterSigner = require("../../scripts/getMasterSigner")
|
||||||
|
|
||||||
|
const addresses = require("../../scripts/constant/addresses");
|
||||||
|
const abis = require("../../scripts/constant/abis");
|
||||||
|
const constants = require("../../scripts/constant/constant");
|
||||||
|
const tokens = require("../../scripts/constant/tokens");
|
||||||
|
|
||||||
|
const connectorMakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/makerdao/main.sol/ConnectV1BMakerDAO.json")
|
||||||
|
|
||||||
|
describe("B.Maker", function () {
|
||||||
|
const connectorName = "B.MAKER-TEST-A"
|
||||||
|
|
||||||
|
let dsaWallet0;
|
||||||
|
let dsaWallet1;
|
||||||
|
let masterSigner;
|
||||||
|
let instaConnectorsV2;
|
||||||
|
let connector;
|
||||||
|
let manager;
|
||||||
|
let vat;
|
||||||
|
let dai;
|
||||||
|
|
||||||
|
const wallets = provider.getWallets()
|
||||||
|
const [wallet0, wallet1, wallet2, wallet3] = wallets
|
||||||
|
before(async () => {
|
||||||
|
masterSigner = await getMasterSigner(wallet3)
|
||||||
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||||
|
connector = await deployAndEnableConnector({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact: connectorMakerArtifacts,
|
||||||
|
signer: masterSigner,
|
||||||
|
connectors: instaConnectorsV2
|
||||||
|
})
|
||||||
|
|
||||||
|
manager = await ethers.getContractAt("BManagerLike", "0x3f30c2381CD8B917Dd96EB2f1A4F96D91324BBed")
|
||||||
|
vat = await ethers.getContractAt("../artifacts/contracts/mainnet/connectors/b.protocol/makerdao/interface.sol:VatLike", await manager.vat())
|
||||||
|
dai = await ethers.getContractAt("../artifacts/contracts/mainnet/common/interfaces.sol:TokenInterface", tokens.dai.address)
|
||||||
|
|
||||||
|
console.log("Connector address", connector.address)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("test veryClose.", async function () {
|
||||||
|
expect(veryClose(1000001, 1000000)).to.be.true
|
||||||
|
expect(veryClose(1000000, 1000001)).to.be.true
|
||||||
|
expect(veryClose(1003000, 1000001)).to.be.false
|
||||||
|
expect(veryClose(1000001, 1000300)).to.be.false
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should have contracts deployed.", async function () {
|
||||||
|
expect(!!instaConnectorsV2.address).to.be.true;
|
||||||
|
expect(!!connector.address).to.be.true;
|
||||||
|
expect(!!masterSigner.address).to.be.true;
|
||||||
|
expect(await connector.name()).to.be.equal("B.MakerDAO-v1.0");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("DSA wallet setup", function () {
|
||||||
|
it("Should build DSA v2", async function () {
|
||||||
|
dsaWallet0 = await buildDSAv2(wallet0.address)
|
||||||
|
expect(!!dsaWallet0.address).to.be.true;
|
||||||
|
|
||||||
|
dsaWallet1 = await buildDSAv2(wallet1.address)
|
||||||
|
expect(!!dsaWallet1.address).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Deposit ETH 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 wallet1.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 vault
|
||||||
|
let ilk
|
||||||
|
let urn
|
||||||
|
|
||||||
|
it("Should open ETH-A vault Maker", async function () {
|
||||||
|
vault = Number(await manager.cdpi()) + 1
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "open",
|
||||||
|
args: ["ETH-A"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(await manager.owns(vault)).to.be.equal(dsaWallet0.address)
|
||||||
|
|
||||||
|
ilk = await manager.ilks(vault)
|
||||||
|
expect(ilk).to.be.equal("0x4554482d41000000000000000000000000000000000000000000000000000000")
|
||||||
|
|
||||||
|
urn = await manager.urns(vault)
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should deposit", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("7") // 7 ETH
|
||||||
|
const setId = "83478237"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [vault, amount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("3"))
|
||||||
|
|
||||||
|
const urnData = await vat.urns(ilk, urn)
|
||||||
|
expect(urnData[0]).to.be.equal(amount) // ink
|
||||||
|
expect(urnData[1]).to.be.equal("0") // art
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should withdraw", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("1") // 1 ETH
|
||||||
|
const setId = "83478237"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "withdraw",
|
||||||
|
args: [vault, amount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("4"))
|
||||||
|
|
||||||
|
const urnData = await vat.urns(ilk, urn)
|
||||||
|
expect(urnData[0]).to.be.equal(ethers.utils.parseEther("6")) // ink
|
||||||
|
expect(urnData[1]).to.be.equal("0") // art
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should borrow", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("6000") // 6000 dai
|
||||||
|
const setId = "83478237"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "borrow",
|
||||||
|
args: [vault, amount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
const urnData = await vat.urns(ilk, urn)
|
||||||
|
expect(urnData[0]).to.be.equal(ethers.utils.parseEther("6")) // ink
|
||||||
|
expect(urnData[1]).to.be.equal(await daiToArt(vat, ilk, amount)) // art
|
||||||
|
|
||||||
|
expect(await dai.balanceOf(dsaWallet0.address)).to.be.equal(amount)
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should repay", async function () {
|
||||||
|
const amount = ethers.utils.parseEther("500") // 500 dai
|
||||||
|
const setId = "83478237"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "payback",
|
||||||
|
args: [vault, amount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
const urnData = await vat.urns(ilk, urn)
|
||||||
|
expect(urnData[0]).to.be.equal(ethers.utils.parseEther("6")) // ink
|
||||||
|
expect(urnData[1]).to.be.equal(await daiToArt(vat, ilk, ethers.utils.parseEther("5500"))) // art
|
||||||
|
expect(await dai.balanceOf(dsaWallet0.address)).to.be.equal(ethers.utils.parseEther("5500"))
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should depositAndBorrow", async function () {
|
||||||
|
const borrowAmount = ethers.utils.parseEther("1000") // 1000 dai
|
||||||
|
const depositAmount = ethers.utils.parseEther("1") // 1 dai
|
||||||
|
|
||||||
|
const setId = "83478237"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "depositAndBorrow",
|
||||||
|
args: [vault, depositAmount, borrowAmount, 0, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
const urnData = await vat.urns(ilk, urn)
|
||||||
|
expect(urnData[0]).to.be.equal(ethers.utils.parseEther("7")) // ink
|
||||||
|
expect(await dai.balanceOf(dsaWallet0.address)).to.be.equal(ethers.utils.parseEther("6500"))
|
||||||
|
// calculation is not precise as the jug was dripped
|
||||||
|
expect(veryClose(urnData[1], await daiToArt(vat, ilk, ethers.utils.parseEther("6500")))).to.be.true
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("1"))
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should close", async function () {
|
||||||
|
// open a new vault
|
||||||
|
const newVault = vault + 1
|
||||||
|
let spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "open",
|
||||||
|
args: ["ETH-A"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
let tx = await dsaWallet1.connect(wallet1).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
let receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(await manager.owns(newVault)).to.be.equal(dsaWallet1.address)
|
||||||
|
|
||||||
|
ilk = await manager.ilks(newVault)
|
||||||
|
expect(ilk).to.be.equal("0x4554482d41000000000000000000000000000000000000000000000000000000")
|
||||||
|
|
||||||
|
urn = await manager.urns(newVault)
|
||||||
|
|
||||||
|
// deposit and borrow
|
||||||
|
const borrowAmount = ethers.utils.parseEther("6000") // 6000 dai
|
||||||
|
const depositAmount = ethers.utils.parseEther("5") // 5 ETH
|
||||||
|
|
||||||
|
spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "depositAndBorrow",
|
||||||
|
args: [newVault, depositAmount, borrowAmount, 0, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
tx = await dsaWallet1.connect(wallet1).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
receipt = await tx.wait()
|
||||||
|
|
||||||
|
const setId = 0
|
||||||
|
|
||||||
|
// repay borrow
|
||||||
|
spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "payback",
|
||||||
|
args: [newVault, borrowAmount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
tx = await dsaWallet1.connect(wallet1).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
receipt = await tx.wait()
|
||||||
|
|
||||||
|
// withdraw deposit
|
||||||
|
spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "withdraw",
|
||||||
|
args: [newVault, depositAmount, 0, setId]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
tx = await dsaWallet1.connect(wallet1).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
receipt = await tx.wait()
|
||||||
|
|
||||||
|
// close
|
||||||
|
spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "close",
|
||||||
|
args: [newVault]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
tx = await dsaWallet1.connect(wallet1).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
receipt = await tx.wait()
|
||||||
|
|
||||||
|
expect(await manager.owns(newVault)).not.to.be.equal(dsaWallet1.address)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
async function daiToArt(vat, ilk, dai) {
|
||||||
|
const ilks = await vat.ilks(ilk)
|
||||||
|
const rate = ilks[1] // second parameter
|
||||||
|
const _1e27 = ethers.utils.parseEther("1000000000") // 1e9 * 1e18
|
||||||
|
const art = dai.mul(_1e27).div(rate)
|
||||||
|
|
||||||
|
return art.add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function veryClose(n1, n2) {
|
||||||
|
n1 = web3.utils.toBN(n1)
|
||||||
|
n2 = web3.utils.toBN(n2)
|
||||||
|
|
||||||
|
_10000 = web3.utils.toBN(10000)
|
||||||
|
_9999 = web3.utils.toBN(9999)
|
||||||
|
|
||||||
|
if(n1.mul(_10000).lt(n2.mul(_9999))) return false
|
||||||
|
if(n2.mul(_10000).lt(n1.mul(_9999))) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
324
test/uniswap/uniswap.test.js
Normal file
324
test/uniswap/uniswap.test.js
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const hre = require("hardhat");
|
||||||
|
const { web3, deployments, waffle, ethers } = hre;
|
||||||
|
const { provider, deployContract } = waffle
|
||||||
|
|
||||||
|
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
|
||||||
|
const buildDSAv2 = require("../../scripts/buildDSAv2")
|
||||||
|
const encodeSpells = require("../../scripts/encodeSpells.js")
|
||||||
|
const encodeFlashcastData = require("../../scripts/encodeFlashcastData.js")
|
||||||
|
const getMasterSigner = require("../../scripts/getMasterSigner")
|
||||||
|
const addLiquidity = require("../../scripts/addLiquidity");
|
||||||
|
|
||||||
|
const addresses = require("../../scripts/constant/addresses");
|
||||||
|
const abis = require("../../scripts/constant/abis");
|
||||||
|
const constants = require("../../scripts/constant/constant");
|
||||||
|
const tokens = require("../../scripts/constant/tokens");
|
||||||
|
const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json")
|
||||||
|
|
||||||
|
const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswapV3/main.sol/ConnectV2UniswapV3.json");
|
||||||
|
const { eth } = require("../../scripts/constant/tokens");
|
||||||
|
const { BigNumber } = require("ethers");
|
||||||
|
|
||||||
|
const FeeAmount = {
|
||||||
|
LOW: 500,
|
||||||
|
MEDIUM: 3000,
|
||||||
|
HIGH: 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
const TICK_SPACINGS = {
|
||||||
|
500: 10,
|
||||||
|
3000: 60,
|
||||||
|
10000: 200
|
||||||
|
}
|
||||||
|
|
||||||
|
const USDT_ADDR = "0xdac17f958d2ee523a2206206994597c13d831ec7"
|
||||||
|
const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"
|
||||||
|
|
||||||
|
let tokenIds = []
|
||||||
|
let liquidities = []
|
||||||
|
const abiCoder = ethers.utils.defaultAbiCoder
|
||||||
|
|
||||||
|
describe("UniswapV3", function () {
|
||||||
|
const connectorName = "UniswapV3-v1"
|
||||||
|
|
||||||
|
let dsaWallet0
|
||||||
|
let masterSigner;
|
||||||
|
let instaConnectorsV2;
|
||||||
|
let connector;
|
||||||
|
let nftManager;
|
||||||
|
|
||||||
|
const wallets = provider.getWallets()
|
||||||
|
const [wallet0, wallet1, wallet2, wallet3] = wallets
|
||||||
|
before(async () => {
|
||||||
|
masterSigner = await getMasterSigner(wallet3)
|
||||||
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||||
|
nftManager = await ethers.getContractAt(nftManagerAbi, "0xC36442b4a4522E871399CD717aBDD847Ab11FE88");
|
||||||
|
connector = await deployAndEnableConnector({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact: connectV2UniswapV3Artifacts,
|
||||||
|
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(!!masterSigner.address).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 & DAI 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("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Deposit ETH & USDT 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("usdt", dsaWallet0.address, ethers.utils.parseEther("100000"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Main", function () {
|
||||||
|
|
||||||
|
it("Should mint successfully", async function () {
|
||||||
|
const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH
|
||||||
|
const daiAmount = ethers.utils.parseEther("400") // 1 ETH
|
||||||
|
const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH
|
||||||
|
const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
|
||||||
|
|
||||||
|
const getIds = ["0", "0"]
|
||||||
|
const setId = "0"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "mint",
|
||||||
|
args: [
|
||||||
|
DAI_ADDR,
|
||||||
|
ethAddress,
|
||||||
|
FeeAmount.MEDIUM,
|
||||||
|
getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
daiAmount,
|
||||||
|
ethAmount,
|
||||||
|
"500000000000000000",
|
||||||
|
getIds,
|
||||||
|
setId
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "mint",
|
||||||
|
args: [
|
||||||
|
DAI_ADDR,
|
||||||
|
USDT_ADDR,
|
||||||
|
FeeAmount.MEDIUM,
|
||||||
|
getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
daiAmount,
|
||||||
|
usdtAmount,
|
||||||
|
"300000000000000000",
|
||||||
|
getIds,
|
||||||
|
setId
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "mint",
|
||||||
|
args: [
|
||||||
|
ethAddress,
|
||||||
|
USDT_ADDR,
|
||||||
|
FeeAmount.MEDIUM,
|
||||||
|
getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
|
||||||
|
ethAmount,
|
||||||
|
usdtAmount,
|
||||||
|
"300000000000000000",
|
||||||
|
getIds,
|
||||||
|
setId
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
let receipt = await tx.wait()
|
||||||
|
let castEvent = new Promise((resolve, reject) => {
|
||||||
|
dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
|
||||||
|
const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]);
|
||||||
|
const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[2]);
|
||||||
|
tokenIds.push(params[0]);
|
||||||
|
tokenIds.push(params1[0]);
|
||||||
|
liquidities.push(params[1]);
|
||||||
|
event.removeListener();
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
eventNames,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('timeout'));
|
||||||
|
}, 60000)
|
||||||
|
});
|
||||||
|
|
||||||
|
let event = await castEvent
|
||||||
|
|
||||||
|
const data = await nftManager.positions(tokenIds[0])
|
||||||
|
|
||||||
|
expect(data.liquidity).to.be.equals(liquidities[0]);
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should deposit successfully", async function () {
|
||||||
|
const daiAmount = ethers.utils.parseEther("400") // 1 ETH
|
||||||
|
const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH
|
||||||
|
const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH
|
||||||
|
const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
|
||||||
|
|
||||||
|
const getIds = ["0", "0"]
|
||||||
|
const setId = "0"
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [
|
||||||
|
tokenIds[0],
|
||||||
|
daiAmount,
|
||||||
|
ethAmount,
|
||||||
|
"500000000000000000",
|
||||||
|
getIds,
|
||||||
|
setId
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
|
||||||
|
let castEvent = new Promise((resolve, reject) => {
|
||||||
|
dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
|
||||||
|
const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[0]);
|
||||||
|
liquidities[0] = liquidities[0].add(params[1]);
|
||||||
|
event.removeListener();
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
eventNames,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('timeout'));
|
||||||
|
}, 60000)
|
||||||
|
});
|
||||||
|
|
||||||
|
let event = await castEvent
|
||||||
|
|
||||||
|
const data = await nftManager.positions(tokenIds[0])
|
||||||
|
expect(data.liquidity).to.be.equals(liquidities[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);
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should collect successfully", async function () {
|
||||||
|
|
||||||
|
const ethAmount = ethers.utils.parseEther("0.2") // 1 ETH
|
||||||
|
const daiAmount = ethers.utils.parseEther("800") // 1 ETH
|
||||||
|
const getIds = ["0", "0"]
|
||||||
|
const setIds = ["0", "0"]
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "collect",
|
||||||
|
args: [
|
||||||
|
tokenIds[0],
|
||||||
|
daiAmount,
|
||||||
|
ethAmount,
|
||||||
|
getIds,
|
||||||
|
setIds
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should burn successfully", async function () {
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "burn",
|
||||||
|
args: [
|
||||||
|
tokenIds[0]
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const getMinTick = (tickSpacing) => Math.ceil(-887272 / tickSpacing) * tickSpacing
|
||||||
|
const getMaxTick = (tickSpacing) => Math.floor(887272 / tickSpacing) * tickSpacing
|
Loading…
Reference in New Issue
Block a user