Skip to content

Commit

Permalink
Added Uniswap into Channel implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
chompomonim committed Sep 21, 2020
1 parent b22581f commit 38091d6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 22 deletions.
16 changes: 10 additions & 6 deletions contracts/ChannelImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { IERC20Token } from "./interfaces/IERC20Token.sol";
import { IHermesContract } from "./interfaces/IHermesContract.sol";
import { IUniswapV2Router } from "./uniswap/IUniswapV2Router.sol";
import { FundsRecovery } from "./FundsRecovery.sol";

contract ChannelImplementation is FundsRecovery {
Expand All @@ -28,7 +29,7 @@ contract ChannelImplementation is FundsRecovery {
ExitRequest public exitRequest;
Hermes public hermes;
address public operator; // channel operator = sha3(IdentityPublicKey)[:20]
address public dex;
IUniswapV2Router internal dex; // any uniswap v2 compatible dex router address

event PromiseSettled(address beneficiary, uint256 amount, uint256 totalSettled);
event ChannelInitialised(address operator, address hermes);
Expand All @@ -39,22 +40,25 @@ contract ChannelImplementation is FundsRecovery {
------------------------------------------- SETUP -------------------------------------------
*/

// Fallback function - redirect ethers topup into DEX
// Fallback function - exchange received ETH into MYST
receive() external payable {
(bool success, ) = address(dex).call{value: msg.value}(msg.data);
require(success, "Tx was rejected by DEX");
address[] memory path = new address[](2);
path[0] = dex.WETH();
path[1] = address(token);

dex.swapExactETHForTokens{value: msg.value}(0, path, address(this), block.timestamp);
}

// Because of proxy pattern this function is used insted of constructor.
// Have to be called right after proxy deployment.
function initialize(address _token, address _dex, address _identityHash, address _hermesId, uint256 _fee) public {
function initialize(address _token, address _dexAddress, address _identityHash, address _hermesId, uint256 _fee) public {
require(!isInitialized(), "Is already initialized");
require(_identityHash != address(0), "Identity can't be zero");
require(_hermesId != address(0), "HermesID can't be zero");
require(_token != address(0), "Token can't be deployd into zero address");

token = IERC20Token(_token);
dex = _dex;
dex = IUniswapV2Router(_dexAddress);

// Transfer required fee to msg.sender (most probably Registry)
if (_fee > 0) {
Expand Down
26 changes: 24 additions & 2 deletions test/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
const { BN } = require('@openzeppelin/test-helpers')
const {
topUpTokens,
topUpEthers
topUpEthers,
setupDEX
} = require('./utils/index.js')
const wallet = require('./utils/wallet.js')
const { generatePromise, signExitRequest, constructPayload } = require('./utils/client.js')
Expand All @@ -26,8 +27,9 @@ contract('Channel Contract Implementation tests', ([txMaker, ...otherAccounts])
let token, channel
before(async () => {
token = await MystToken.new()
const dex = await setupDEX(token, txMaker)
hermesImplementation = await TestHermesImplementation.new(token.address, hermes.address, 0, OneToken)
channel = await TestChannelImplementation.new(token.address, identityHash, hermesImplementation.address, Zero)
channel = await TestChannelImplementation.new(token.address, dex.address, identityHash, hermesImplementation.address, Zero)

// Give some ethers for gas for hermes
topUpEthers(txMaker, hermes.address, OneEther)
Expand Down Expand Up @@ -202,4 +204,24 @@ contract('Channel Contract Implementation tests', ([txMaker, ...otherAccounts])
const exitRequest = await channel.exitRequest()
expect(exitRequest.beneficiary).to.be.equal(beneficiary)
})

/**
* Testing topup with ETH via DEX
*/
it('should exchange ethers into tokens', async () => {
const userAccount = otherAccounts[0]
const initialChannelBalance = await token.balanceOf(channel.address)
const ethersAmount = new BN('2000')
const expectedTokens = new BN('3987')

// Send some ethers into payment channel
await channel.sendTransaction({
from: userAccount,
value: ethersAmount,
gas: 200000
})

const channelBalance = await token.balanceOf(channel.address)
channelBalance.should.be.bignumber.equal(initialChannelBalance.add(expectedTokens))
})
})
7 changes: 2 additions & 5 deletions test/contracts/TestChannelImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@
pragma solidity >=0.7.0;

import { ChannelImplementation } from "../../contracts/ChannelImplementation.sol";
import { MystDEX } from "../../contracts/MystDEX.sol";


// Helper functions to be used in tests
contract TestChannelImplementation is ChannelImplementation {
uint256 constant TEST_DELAY_BLOCKS = 4;

// Constructor is needed only in tests where we don't use minimal Proxies and testing implementation directly
constructor (address _token, address _identityHash, address _hermesAddress, uint256 _fee) {
MystDEX _dex = new MystDEX();
initialize(_token, address(_dex), _identityHash, _hermesAddress, _fee);
constructor (address _token, address _dex, address _identityHash, address _hermesAddress, uint256 _fee) {
initialize(_token, _dex, _identityHash, _hermesAddress, _fee);
}

function getTimelock() internal view override returns (uint256) {
Expand Down
20 changes: 11 additions & 9 deletions test/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const IUniswapV2Router = artifacts.require("IUniswapV2Router")

const deployRouter02Tx = require('../../scripts/UniswapV2Router02.json')
const OneToken = web3.utils.toWei(new BN('1000000000000000000'), 'wei')
const HalfETH = web3.utils.toWei(new BN('500000000000000000'), 'wei')

// CREATE2 address is calculated this way:
// keccak("0xff++msg.sender++salt++keccak(byteCode)")
Expand Down Expand Up @@ -106,16 +107,17 @@ async function setupDEX(token, txMaker) {
// Map with abi
const dex = await IUniswapV2Router.at(deployRouter02Tx.contractAddr)

// Setup traiding pair and provide liquidity
const farFuture = 2147483646 // year 2038, end of unix time epoch
await topUpTokens(token, txMaker, OneToken)
await token.approve(dex.address, OneToken)

await dex.addLiquidityETH(token.address, 10000000, 10000000, 5000000, txMaker, farFuture, {
from: txMaker,
value: 5000000
})
// Setup traiding pair and provide liquidity (if there is none)
if ((await token.balanceOf(deployRouter02Tx.contractAddr)).toNumber() === 0) {
const farFuture = 2147483646 // year 2038, end of unix time epoch
await topUpTokens(token, txMaker, OneToken)
await token.approve(dex.address, OneToken)

await dex.addLiquidityETH(token.address, OneToken, OneToken, HalfETH, txMaker, farFuture, {
from: txMaker,
value: HalfETH
})
}
return dex
}

Expand Down

0 comments on commit 38091d6

Please sign in to comment.