// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma abicoder v2; /** * @title Ubiquity. * @dev Ubiquity Dollar (uAD). */ import { TokenInterface } from "../../common/interfaces.sol"; import { IUbiquityBondingV2, IUbiquityMetaPool, I3Pool } from "./interfaces.sol"; import { Helpers } from "./helpers.sol"; import { Events } from "./events.sol"; abstract contract UbiquityResolver is Helpers, Events { /** * @dev Deposit into Ubiquity protocol * @notice 3POOL (DAI / USDC / USDT) => METAPOOL (3CRV / uAD) => uAD3CRV-f => Ubiquity BondingShare * @notice STEP 1 : 3POOL (DAI / USDC / USDT) => 3CRV * @notice STEP 2 : METAPOOL(3CRV / UAD) => uAD3CRV-f * @notice STEP 3 : uAD3CRV-f => Ubiquity BondingShare * @param token Token deposited : DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f * @param amount Amount of tokens to deposit (For max: `uint256(-1)`) * @param durationWeeks Duration in weeks tokens will be locked (4-208) * @param getId ID to retrieve amt. * @param setId ID stores the bonding share id of tokens deposited. */ function deposit( address token, uint256 amount, uint256 durationWeeks, uint256 getId, uint256 setId ) external payable returns (string memory _eventName, bytes memory _eventParam) { address UAD3CRVf = getUADCRV3(); bool[6] memory tok = [ token == DAI, // 0 token == USDC, // 1 token == USDT, // 2 token == CRV3, // 3 token == getUAD(), // 4 token == UAD3CRVf // 5 ]; require( // DAI / USDC / USDT / CRV3 / UAD / UAD3CRVF tok[0] || tok[1] || tok[2] || tok[3] || tok[4] || tok[5], "Invalid token: must be DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f" ); uint256 _amount = getUint(getId, amount); uint256 lpAmount; // Full balance if amount = -1 if (_amount == uint256(-1)) { _amount = getTokenBal(TokenInterface(token)); } // STEP 1 : SwapTo3CRV : Deposit DAI, USDC or USDT into 3Pool to get 3Crv LPs // DAI / USDC / USDT if (tok[0] || tok[1] || tok[2]) { uint256[3] memory amounts1; if (tok[0]) amounts1[0] = _amount; else if (tok[1]) amounts1[1] = _amount; else if (tok[2]) amounts1[2] = _amount; approve(TokenInterface(token), Pool3, _amount); I3Pool(Pool3).add_liquidity(amounts1, 0); } // STEP 2 : ProvideLiquidityToMetapool : Deposit in uAD3CRV pool to get uAD3CRV-f LPs // DAI / USDC / USDT / CRV3 / UAD if (tok[0] || tok[1] || tok[2] || tok[3] || tok[4]) { uint256[2] memory amounts2; address token2 = token; uint256 _amount2; if (tok[4]) { _amount2 = _amount; amounts2[0] = _amount2; } else { if (tok[3]) { _amount2 = _amount; } else { token2 = CRV3; _amount2 = getTokenBal(TokenInterface(token2)); } amounts2[1] = _amount2; } approve(TokenInterface(token2), UAD3CRVf, _amount2); lpAmount = IUbiquityMetaPool(UAD3CRVf).add_liquidity(amounts2, 0); } // STEP 3 : Farm/ApeIn : Deposit uAD3CRV-f LPs into UbiquityBondingV2 and get Ubiquity Bonding Shares // UAD3CRVF if (tok[5]) { lpAmount = _amount; } address bonding = ubiquityManager.bondingContractAddress(); approve(TokenInterface(UAD3CRVf), bonding, lpAmount); uint256 bondingShareId = IUbiquityBondingV2(bonding).deposit( lpAmount, durationWeeks ); setUint(setId, bondingShareId); _eventName = "LogDeposit(address,address,uint256,uint256,uint256,uint256,uint256,uint256)"; _eventParam = abi.encode( address(this), token, amount, bondingShareId, lpAmount, durationWeeks, getId, setId ); } /** * @dev Withdraw from Ubiquity protocol * @notice Ubiquity BondingShare => uAD3CRV-f => METAPOOL (3CRV / uAD) => 3POOL (DAI / USDC / USDT) * @notice STEP 1 : Ubiquity BondingShare => uAD3CRV-f * @notice STEP 2 : uAD3CRV-f => METAPOOL(3CRV / UAD) * @notice STEP 3 : 3CRV => 3POOL (DAI / USDC / USDT) * @param bondingShareId Bonding Share Id to withdraw * @param token Token to withdraw to : DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f * @param getId ID * @param setId ID */ function withdraw( uint256 bondingShareId, address token, uint256 getId, uint256 setId ) external payable returns (string memory _eventName, bytes memory _eventParam) { address UAD3CRVf = getUADCRV3(); bool[6] memory tok = [ token == DAI, // 0 token == USDC, // 1 token == USDT, // 2 token == CRV3, // 3 token == getUAD(), // 4 token == UAD3CRVf // 5 ]; require( // DAI / USDC / USDT / CRV3 / UAD / UAD3CRVF tok[0] || tok[1] || tok[2] || tok[3] || tok[4] || tok[5], "Invalid token: must be DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f" ); uint256 _bondingShareId = getUint(getId, bondingShareId); // Get Bond IUbiquityBondingV2.Bond memory bond = IUbiquityBondingV2( ubiquityManager.bondingShareAddress() ).getBond(_bondingShareId); require(address(this) == bond.minter, "Not bond owner"); // STEP 1 : Withdraw Ubiquity Bonding Shares to get back uAD3CRV-f LPs address bonding = ubiquityManager.bondingContractAddress(); IUbiquityBondingV2(bonding).removeLiquidity( bond.lpAmount, _bondingShareId ); // STEP 2 : Withdraw uAD3CRV-f LPs to get back uAD or 3Crv // DAI / USDC / USDT / CRV3 / UAD if (tok[0] || tok[1] || tok[2] || tok[3] || tok[4]) { uint256 amount2 = getTokenBal(TokenInterface(UAD3CRVf)); IUbiquityMetaPool(UAD3CRVf).remove_liquidity_one_coin( amount2, tok[4] ? 0 : 1, 0 ); } // STEP 3 : Withdraw 3Crv LPs from 3Pool to get back DAI, USDC or USDT // DAI / USDC / USDT if (tok[0] || tok[1] || tok[2]) { uint256 amount1 = getTokenBal(TokenInterface(CRV3)); I3Pool(Pool3).remove_liquidity_one_coin( amount1, tok[0] ? 0 : (tok[1] ? 1 : 2), 0 ); } uint256 amount = getTokenBal(TokenInterface(token)); setUint(setId, amount); _eventName = "LogWithdraw(address,uint256,uint256,uint256,address,uint256,uint256,uint256)"; _eventParam = abi.encode( address(this), _bondingShareId, bond.lpAmount, bond.endBlock, token, amount, getId, setId ); } } contract ConnectV2Ubiquity is UbiquityResolver { string public constant name = "Ubiquity-v1"; }