mirror of
				https://github.com/Instadapp/dsa-connectors.git
				synced 2024-07-29 22:37:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			362 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
| //SPDX-License-Identifier: MIT
 | |
| pragma solidity ^0.7.0;
 | |
| 
 | |
| import { DSMath } from "../../../common/math.sol";
 | |
| import { Basic } from "../../../common/basic.sol";
 | |
| import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
 | |
| import "./events.sol";
 | |
| import "./interfaces.sol";
 | |
| 
 | |
| abstract contract Helper is DSMath, Basic {
 | |
| 	/**
 | |
| 	 * @dev Aave referal code
 | |
| 	 */
 | |
| 	uint16 internal constant referalCode = 3228;
 | |
| 
 | |
| 	/**
 | |
| 	 * @dev AaveV2 Lending Pool Provider
 | |
| 	 */
 | |
| 	AaveV2LendingPoolProviderInterface internal constant aaveV2Provider =
 | |
| 		AaveV2LendingPoolProviderInterface(
 | |
| 			0xb6A86025F0FE1862B372cb0ca18CE3EDe02A318f // v2 address: LendingPoolAddressProvider avax
 | |
| 		);
 | |
| 
 | |
| 	/**
 | |
| 	 * @dev AaveV3 Lending Pool Provider
 | |
| 	 */
 | |
| 	AaveV3PoolProviderInterface internal constant aaveV3Provider =
 | |
| 		AaveV3PoolProviderInterface(
 | |
| 			0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb // v3 - PoolAddressesProvider Avalanche
 | |
| 		);
 | |
| 
 | |
| 	/**
 | |
| 	 * @dev Aave Protocol Data Provider
 | |
| 	 */
 | |
| 	AaveV2DataProviderInterface internal constant aaveV2Data =
 | |
| 		AaveV2DataProviderInterface(0x65285E9dfab318f57051ab2b139ccCf232945451); // aave v2 - avax
 | |
| 
 | |
| 	function getIsColl(address token, address user)
 | |
| 		internal
 | |
| 		view
 | |
| 		returns (bool isCol)
 | |
| 	{
 | |
| 		(, , , , , , , , isCol) = aaveV2Data.getUserReserveData(token, user);
 | |
| 	}
 | |
| 
 | |
| 	struct ImportData {
 | |
| 		address[] _supplyTokens;
 | |
| 		address[] _supplyTokensV3;
 | |
| 		address[] _borrowTokens;
 | |
| 		address[] _borrowTokensV3;
 | |
| 		ATokenV2Interface[] aTokens;
 | |
| 		uint256[] supplyAmts;
 | |
| 		uint256[] variableBorrowAmts;
 | |
| 		uint256[] variableBorrowAmtsWithFee;
 | |
| 		uint256[] stableBorrowAmts;
 | |
| 		uint256[] stableBorrowAmtsWithFee;
 | |
| 		uint256[] totalBorrowAmts;
 | |
| 		uint256[] totalBorrowAmtsWithFee;
 | |
| 		bool convertStable;
 | |
| 	}
 | |
| 
 | |
| 	struct ImportInputData {
 | |
| 		address[] supplyTokens;
 | |
| 		address[] borrowTokens;
 | |
| 		bool convertStable;
 | |
| 		uint256[] flashLoanFees;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| contract _AaveHelper is Helper {
 | |
| 	/*
 | |
| 	 ** Convert Avalanche Bridge tokens to Offical tokens. Like USDC.e to USDC
 | |
| 	 */
 | |
| 	function convertABTokens(address _token) internal pure returns (address) {
 | |
| 		if (_token == 0xc7198437980c041c805A1EDcbA50c1Ce5db95118) {
 | |
| 			// USDT.e => USDT
 | |
| 			return 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7;
 | |
| 		} else if (_token == 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664) {
 | |
| 			// USDC.e => USDC
 | |
| 			return 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E;
 | |
| 		} else {
 | |
| 			return _token;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function getBorrowAmountV2(address _token, address userAccount)
 | |
| 		internal
 | |
| 		view
 | |
| 		returns (uint256 stableBorrow, uint256 variableBorrow)
 | |
| 	{
 | |
| 		(
 | |
| 			,
 | |
| 			address stableDebtTokenAddress,
 | |
| 			address variableDebtTokenAddress
 | |
| 		) = aaveV2Data.getReserveTokensAddresses(_token);
 | |
| 
 | |
| 		stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf(
 | |
| 			userAccount
 | |
| 		);
 | |
| 		variableBorrow = ATokenV2Interface(variableDebtTokenAddress).balanceOf(
 | |
| 			userAccount
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	function getBorrowAmountsV2(
 | |
| 		address userAccount,
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		ImportInputData memory inputData,
 | |
| 		ImportData memory data
 | |
| 	) internal returns (ImportData memory) {
 | |
| 		if (inputData.borrowTokens.length > 0) {
 | |
| 			data._borrowTokens = new address[](inputData.borrowTokens.length);
 | |
| 			data._borrowTokensV3 = new address[](inputData.borrowTokens.length);
 | |
| 			data.variableBorrowAmts = new uint256[](
 | |
| 				inputData.borrowTokens.length
 | |
| 			);
 | |
| 			data.stableBorrowAmts = new uint256[](
 | |
| 				inputData.borrowTokens.length
 | |
| 			);
 | |
| 			data.variableBorrowAmtsWithFee = new uint256[](
 | |
| 				inputData.borrowTokens.length
 | |
| 			);
 | |
| 			data.stableBorrowAmtsWithFee = new uint256[](
 | |
| 				inputData.borrowTokens.length
 | |
| 			);
 | |
| 			data.totalBorrowAmtsWithFee = new uint256[](
 | |
| 				inputData.borrowTokens.length
 | |
| 			);
 | |
| 			data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
 | |
| 
 | |
| 			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
 | |
| 				for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
 | |
| 					if (j != i) {
 | |
| 						require(
 | |
| 							inputData.borrowTokens[i] !=
 | |
| 								inputData.borrowTokens[j],
 | |
| 							"token-repeated"
 | |
| 						);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
 | |
| 				address _token = inputData.borrowTokens[i] == avaxAddr
 | |
| 					? wavaxAddr
 | |
| 					: inputData.borrowTokens[i];
 | |
| 				data._borrowTokens[i] = _token;
 | |
| 				data._borrowTokensV3[i] = convertABTokens(_token);
 | |
| 
 | |
| 				(
 | |
| 					data.stableBorrowAmts[i],
 | |
| 					data.variableBorrowAmts[i]
 | |
| 				) = getBorrowAmountV2(_token, userAccount);
 | |
| 
 | |
| 				if (data.variableBorrowAmts[i] != 0) {
 | |
| 					data.variableBorrowAmtsWithFee[i] = add(
 | |
| 						data.variableBorrowAmts[i],
 | |
| 						inputData.flashLoanFees[i]
 | |
| 					);
 | |
| 					data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
 | |
| 				} else {
 | |
| 					data.stableBorrowAmtsWithFee[i] = add(
 | |
| 						data.stableBorrowAmts[i],
 | |
| 						inputData.flashLoanFees[i]
 | |
| 					);
 | |
| 				}
 | |
| 
 | |
| 				data.totalBorrowAmts[i] = add(
 | |
| 					data.stableBorrowAmts[i],
 | |
| 					data.variableBorrowAmts[i]
 | |
| 				);
 | |
| 				data.totalBorrowAmtsWithFee[i] = add(
 | |
| 					data.stableBorrowAmtsWithFee[i],
 | |
| 					data.variableBorrowAmtsWithFee[i]
 | |
| 				);
 | |
| 
 | |
| 				if (data.totalBorrowAmts[i] > 0) {
 | |
| 					uint256 _amt = data.totalBorrowAmts[i];
 | |
| 					TokenInterface(_token).approve(address(aaveV2), _amt);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		return data;
 | |
| 	}
 | |
| 
 | |
| 	function getSupplyAmountsV2(
 | |
| 		address userAccount,
 | |
| 		ImportInputData memory inputData,
 | |
| 		ImportData memory data
 | |
| 	) internal view returns (ImportData memory) {
 | |
| 		data.supplyAmts = new uint256[](inputData.supplyTokens.length);
 | |
| 		data._supplyTokens = new address[](inputData.supplyTokens.length);
 | |
| 		data._supplyTokensV3 = new address[](inputData.supplyTokens.length);
 | |
| 		data.aTokens = new ATokenV2Interface[](inputData.supplyTokens.length);
 | |
| 
 | |
| 		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
 | |
| 			for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
 | |
| 				if (j != i) {
 | |
| 					require(
 | |
| 						inputData.supplyTokens[i] != inputData.supplyTokens[j],
 | |
| 						"token-repeated"
 | |
| 					);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
 | |
| 			address _token = inputData.supplyTokens[i] == avaxAddr
 | |
| 				? wavaxAddr
 | |
| 				: inputData.supplyTokens[i];
 | |
| 			(address _aToken, , ) = aaveV2Data.getReserveTokensAddresses(
 | |
| 				_token
 | |
| 			);
 | |
| 			data._supplyTokens[i] = _token;
 | |
| 			data._supplyTokensV3[i] = convertABTokens(_token);
 | |
| 
 | |
| 			data.aTokens[i] = ATokenV2Interface(_aToken);
 | |
| 			data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
 | |
| 		}
 | |
| 
 | |
| 		return data;
 | |
| 	}
 | |
| 
 | |
| 	function _paybackBehalfOneV2(
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		address token,
 | |
| 		uint256 amt,
 | |
| 		uint256 rateMode,
 | |
| 		address user
 | |
| 	) private {
 | |
| 		aaveV2.repay(token, amt, rateMode, user);
 | |
| 	}
 | |
| 
 | |
| 	function _PaybackStableV2(
 | |
| 		uint256 _length,
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		address[] memory tokens,
 | |
| 		uint256[] memory amts,
 | |
| 		address user
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				_paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 1, user);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _PaybackVariableV2(
 | |
| 		uint256 _length,
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		address[] memory tokens,
 | |
| 		uint256[] memory amts,
 | |
| 		address user
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				_paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 2, user);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _TransferAtokensV2(
 | |
| 		uint256 _length,
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		ATokenV2Interface[] memory atokenContracts,
 | |
| 		uint256[] memory amts,
 | |
| 		address[] memory tokens,
 | |
| 		address userAccount
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				uint256 _amt = amts[i];
 | |
| 				require(
 | |
| 					atokenContracts[i].transferFrom(
 | |
| 						userAccount,
 | |
| 						address(this),
 | |
| 						_amt
 | |
| 					),
 | |
| 					"allowance?"
 | |
| 				);
 | |
| 
 | |
| 				if (!getIsColl(tokens[i], address(this))) {
 | |
| 					aaveV2.setUserUseReserveAsCollateral(tokens[i], true);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _WithdrawTokensFromV2(
 | |
| 		uint256 _length,
 | |
| 		AaveV2Interface aaveV2,
 | |
| 		uint256[] memory amts,
 | |
| 		address[] memory tokens
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				uint256 _amt = amts[i];
 | |
| 				address _token = tokens[i];
 | |
| 				aaveV2.withdraw(_token, _amt, address(this));
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _depositTokensV3(
 | |
| 		uint256 _length,
 | |
| 		AaveV3Interface aaveV3,
 | |
| 		uint256[] memory amts,
 | |
| 		address[] memory tokens
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				uint256 _amt = amts[i];
 | |
| 				address _token = tokens[i];
 | |
| 				TokenInterface tokenContract = TokenInterface(_token);
 | |
| 				require(
 | |
| 					tokenContract.balanceOf(address(this)) >= _amt,
 | |
| 					"Insufficient funds to deposit in v3"
 | |
| 				);
 | |
| 				approve(tokenContract, address(aaveV3), _amt);
 | |
| 				aaveV3.supply(_token, _amt, address(this), referalCode);
 | |
| 
 | |
| 				if (!getIsColl(_token, address(this))) {
 | |
| 					aaveV3.setUserUseReserveAsCollateral(_token, true);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _BorrowVariableV3(
 | |
| 		uint256 _length,
 | |
| 		AaveV3Interface aaveV3,
 | |
| 		address[] memory tokens,
 | |
| 		uint256[] memory amts
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				_borrowOneV3(aaveV3, tokens[i], amts[i], 2);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _BorrowStableV3(
 | |
| 		uint256 _length,
 | |
| 		AaveV3Interface aaveV3,
 | |
| 		address[] memory tokens,
 | |
| 		uint256[] memory amts
 | |
| 	) internal {
 | |
| 		for (uint256 i = 0; i < _length; i++) {
 | |
| 			if (amts[i] > 0) {
 | |
| 				_borrowOneV3(aaveV3, tokens[i], amts[i], 1);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function _borrowOneV3(
 | |
| 		AaveV3Interface aaveV3,
 | |
| 		address token,
 | |
| 		uint256 amt,
 | |
| 		uint256 rateMode
 | |
| 	) private {
 | |
| 		aaveV3.borrow(token, amt, rateMode, referalCode, address(this));
 | |
| 	}
 | |
| }
 | 
