mirror of
				https://github.com/Instadapp/dsa-connectors.git
				synced 2024-07-29 22:37:00 +00:00 
			
		
		
		
	b.compound
This commit is contained in:
		
							parent
							
								
									a14f4c6e02
								
							
						
					
					
						commit
						e892d52c51
					
				
							
								
								
									
										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(0xA8F9D4aA7319C54C04404765117ddBf9448E2082);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @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 ConnectV1BCompound is BCompoundResolver {
 | 
			
		||||
    string public name = "B.Compound-v1.0";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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"));
 | 
			
		||||
    });
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user