Created
April 19, 2020 02:41
-
-
Save suhailgme/f72a3c5dd0c77acf81154d6c6512ec8f to your computer and use it in GitHub Desktop.
Unipool_Balancer_Bridge_Zap_v1.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (C) 2020 defizap, dipeshsukhani, nodarjanashia, suhailg | |
// This program is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU Affero General Public License as published by | |
// the Free Software Foundation, either version 2 of the License, or | |
// (at your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU Affero General Public License for more details. | |
// | |
// Visit <https://www.gnu.org/licenses/>for a copy of the GNU Affero General Public License | |
// File: localhost/defizap/node_modules/@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol | |
//@author DeFiZap | |
//@notice this contract enables bridging from uniswap pools to balancer pools. | |
// interface | |
interface IWethToken_Unipool_Balancer_Bridge_Zap_V1 { | |
function deposit() external payable; | |
function withdraw(uint256 amount) external; | |
function withdraw(uint256 amount, address user) external; | |
} | |
interface IBFactory_Unipool_Balancer_Bridge_Zap_V1 { | |
function isBPool(address b) external view returns (bool); | |
} | |
interface IBPool_Unipool_Balancer_Bridge_Zap_V1 { | |
function joinswapExternAmountIn( | |
address tokenIn, | |
uint256 tokenAmountIn, | |
uint256 minPoolAmountOut | |
) external payable returns (uint256 poolAmountOut); | |
function exitswapPoolAmountIn( | |
address tokenOut, | |
uint256 poolAmountIn, | |
uint256 minAmountOut | |
) external payable returns (uint256 tokenAmountOut); | |
} | |
interface IuniswapFactory_Unipool_Balancer_Bridge_Zap_V1 { | |
function getExchange(address token) | |
external | |
view | |
returns (address exchange); | |
} | |
interface Iuniswap_Unipool_Balancer_Bridge_Zap_V1 { | |
// for removing liquidity (returns ETH removed, ERC20 Removed) | |
function removeLiquidity( | |
uint256 amount, | |
uint256 min_eth, | |
uint256 min_tokens, | |
uint256 deadline | |
) external returns (uint256, uint256); | |
// converting ERC20 to ERC20 and transfer | |
function tokenToTokenSwapInput( | |
uint256 tokens_sold, | |
uint256 min_tokens_bought, | |
uint256 min_eth_bought, | |
uint256 deadline, | |
address token_addr | |
) external returns (uint256 tokens_bought); | |
// add liquidity to a pool (returns LP tokens rec) | |
function addLiquidity( | |
uint256 min_liquidity, | |
uint256 max_tokens, | |
uint256 deadline | |
) external payable returns (uint256); | |
function getEthToTokenInputPrice(uint256 eth_sold) | |
external | |
view | |
returns (uint256 tokens_bought); | |
function getTokenToEthInputPrice(uint256 tokens_sold) | |
external | |
view | |
returns (uint256 eth_bought); | |
function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) | |
external | |
payable | |
returns (uint256 tokens_bought); | |
function tokenToEthSwapInput( | |
uint256 tokens_sold, | |
uint256 min_eth, | |
uint256 deadline | |
) external returns (uint256 eth_bought); | |
function balanceOf(address _owner) external view returns (uint256); | |
function transfer(address _to, uint256 _value) external returns (bool); | |
function transferFrom(address from, address to, uint256 tokens) | |
external | |
returns (bool success); | |
} | |
pragma solidity ^0.5.13; | |
import "./OpenZepplinReentrancyGuard.sol"; | |
import "./OpenZepplinSafeMath.sol"; | |
import "./OpenZepplinOwnable.sol"; | |
import "./OpenZepplinIERC20.sol"; | |
contract Unipool_Balancer_Bridge_Zap_V1 is ReentrancyGuard, Ownable { | |
using SafeMath for uint256; | |
bool private stopped = false; | |
uint16 public goodwill; | |
address public dzgoodwillAddress; | |
IuniswapFactory_Unipool_Balancer_Bridge_Zap_V1 public UniSwapFactoryAddress = IuniswapFactory_Unipool_Balancer_Bridge_Zap_V1( | |
0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95 | |
); | |
IBFactory_Unipool_Balancer_Bridge_Zap_V1 BalancerFactory = IBFactory_Unipool_Balancer_Bridge_Zap_V1( | |
0x9424B1412450D0f8Fc2255FAf6046b98213B76Bd | |
); | |
address public WethTokenAddress = address( | |
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | |
); | |
constructor(uint16 _goodwill, address _dzgoodwillAddress) public { | |
goodwill = _goodwill; | |
dzgoodwillAddress = _dzgoodwillAddress; | |
} | |
// circuit breaker modifiers | |
modifier stopInEmergency { | |
if (stopped) { | |
revert("Temporarily Paused"); | |
} else { | |
_; | |
} | |
} | |
function LetsBridge( | |
address _toWhomToIssue, | |
address _FromTokenContractAddress, | |
address _ToBalancerPoolAddress, | |
uint256 _IncomingLP | |
) public payable nonReentrant stopInEmergency returns (bool) { | |
require( | |
BalancerFactory.isBPool(_ToBalancerPoolAddress), | |
"Invalid Balancer Pool" | |
); | |
uint256 goodwillPortion = SafeMath.div( | |
SafeMath.mul(_IncomingLP, goodwill), | |
10000 | |
); | |
(uint256 ethReceived, uint256 erc20received) = _exitFromPool( | |
_IncomingLP, | |
goodwillPortion, | |
_FromTokenContractAddress | |
); | |
uint256 ethBought = _token2Eth( | |
_FromTokenContractAddress, | |
erc20received | |
); | |
uint256 eth2Wrap = ethBought.add(ethReceived); | |
uint256 wrappedEth = _eth2Weth(eth2Wrap); | |
uint256 balancerTokens = _enter2Balancer( | |
wrappedEth, | |
_ToBalancerPoolAddress | |
); | |
require( | |
IERC20(_ToBalancerPoolAddress).transfer( | |
_toWhomToIssue, | |
balancerTokens | |
), | |
"Error in transferring balancer tokens" | |
); | |
} | |
function _enter2Balancer(uint256 wrappedEth, address _ToBalancerPoolAddress) | |
internal | |
returns (uint256 poolAmountOut) | |
{ | |
uint256 allowance = IERC20(WethTokenAddress).allowance( | |
address(this), | |
_ToBalancerPoolAddress | |
); | |
if (allowance < wrappedEth) { | |
IERC20(WethTokenAddress).approve( | |
_ToBalancerPoolAddress, | |
uint256(-1) | |
); | |
} | |
poolAmountOut = IBPool_Unipool_Balancer_Bridge_Zap_V1( | |
_ToBalancerPoolAddress | |
) | |
.joinswapExternAmountIn(WethTokenAddress, wrappedEth, 1); | |
require(poolAmountOut > 0, "Error in entering balancer pool"); | |
} | |
function _eth2Weth(uint256 eth2Wrap) internal returns (uint256 wrappedEth) { | |
IWethToken_Unipool_Balancer_Bridge_Zap_V1(WethTokenAddress) | |
.deposit | |
.value(eth2Wrap)(); | |
wrappedEth = IERC20(WethTokenAddress).balanceOf(address(this)); | |
require(wrappedEth > 0, "Error in wrapping ETH"); | |
} | |
function _token2Eth(address _FromTokenContractAddress, uint256 tokens2Trade) | |
internal | |
returns (uint256 ethBought) | |
{ | |
Iuniswap_Unipool_Balancer_Bridge_Zap_V1 FromUniSwapExchangeContractAddress | |
= Iuniswap_Unipool_Balancer_Bridge_Zap_V1( | |
UniSwapFactoryAddress.getExchange(_FromTokenContractAddress) | |
); | |
IERC20(_FromTokenContractAddress).approve( | |
address(FromUniSwapExchangeContractAddress), | |
tokens2Trade | |
); | |
ethBought = FromUniSwapExchangeContractAddress.tokenToEthSwapInput( | |
tokens2Trade, | |
1, | |
SafeMath.add(now, 1800) | |
); | |
require(ethBought > 0, "Error in swapping ERC"); | |
} | |
function _exitFromPool( | |
uint256 _IncomingLP, | |
uint256 goodwillPortion, | |
address _FromTokenContractAddress | |
) internal returns (uint256 ethReceived, uint256 erc20received) { | |
Iuniswap_Unipool_Balancer_Bridge_Zap_V1 FromUniSwapExchangeContractAddress | |
= Iuniswap_Unipool_Balancer_Bridge_Zap_V1( | |
UniSwapFactoryAddress.getExchange(_FromTokenContractAddress) | |
); | |
require( | |
FromUniSwapExchangeContractAddress.transferFrom( | |
msg.sender, | |
address(this), | |
SafeMath.sub(_IncomingLP, goodwillPortion) | |
), | |
"Error in transferring LP:1" | |
); | |
require( | |
FromUniSwapExchangeContractAddress.transferFrom( | |
msg.sender, | |
dzgoodwillAddress, | |
goodwillPortion | |
), | |
"Error in transferring LP:2" | |
); | |
(ethReceived, erc20received) = FromUniSwapExchangeContractAddress | |
.removeLiquidity( | |
SafeMath.sub(_IncomingLP, goodwillPortion), | |
1, | |
1, | |
SafeMath.add(now, 1800) | |
); | |
} | |
function inCaseTokengetsStuck(IERC20 _TokenAddress) public onlyOwner { | |
uint256 qty = _TokenAddress.balanceOf(address(this)); | |
_TokenAddress.transfer(_owner, qty); | |
} | |
function set_new_goodwill(uint16 _new_goodwill) public onlyOwner { | |
require( | |
_new_goodwill > 0 && _new_goodwill < 10000, | |
"GoodWill Value not allowed" | |
); | |
goodwill = _new_goodwill; | |
} | |
function set_new_dzgoodwillAddress(address _new_dzgoodwillAddress) | |
public | |
onlyOwner | |
{ | |
dzgoodwillAddress = _new_dzgoodwillAddress; | |
} | |
// - to Pause the contract | |
function toggleContractActive() public onlyOwner { | |
stopped = !stopped; | |
} | |
// - to withdraw any ETH balance sitting in the contract | |
function withdraw() public onlyOwner { | |
_owner.transfer(address(this).balance); | |
} | |
// - to kill the contract | |
function destruct() public onlyOwner { | |
selfdestruct(_owner); | |
} | |
function() external payable {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment