Skip to content

Instantly share code, notes, and snippets.

@suhailgme
Created April 19, 2020 02:41
Show Gist options
  • Save suhailgme/f72a3c5dd0c77acf81154d6c6512ec8f to your computer and use it in GitHub Desktop.
Save suhailgme/f72a3c5dd0c77acf81154d6c6512ec8f to your computer and use it in GitHub Desktop.
Unipool_Balancer_Bridge_Zap_v1.sol
// 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