Skip to content

Commit

Permalink
Merge pull request #129 from mysteriumnetwork/feature/pay_and_settle
Browse files Browse the repository at this point in the history
Feature/pay and settle
  • Loading branch information
chompomonim authored Mar 31, 2021
2 parents 7c3933d + 692fcb2 commit 51be353
Show file tree
Hide file tree
Showing 36 changed files with 35,976 additions and 8,636 deletions.
13 changes: 4 additions & 9 deletions contracts/ChannelImplementation.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.4;
pragma solidity 0.7.6;

import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
Expand All @@ -9,10 +9,6 @@ import { IUniswapV2Router } from "./interfaces/IUniswapV2Router.sol";
import { FundsRecovery } from "./FundsRecovery.sol";
import { Utils } from "./Utils.sol";

interface IdentityRegistry {
function getBeneficiary(address _identity) external view returns (address);
function setBeneficiary(address _identity, address _newBeneficiary, bytes memory _signature) external;
}

contract ChannelImplementation is FundsRecovery, Utils {
using ECDSA for bytes32;
Expand All @@ -35,7 +31,6 @@ contract ChannelImplementation is FundsRecovery, Utils {
}

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

// Because of proxy pattern this function is used insted of constructor.
// Have to be called right after proxy deployment.
function initialize(address _token, address _dexAddress, address _identityHash, address _hermesId, uint256 _fee) public {
function initialize(address _token, address _dexAddress, address _identity, address _hermesId, uint256 _fee) public {
require(!isInitialized(), "Is already initialized");
require(_identityHash != address(0), "Identity can't be zero");
require(_identity != 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");

Expand All @@ -73,7 +68,7 @@ contract ChannelImplementation is FundsRecovery, Utils {
token.transfer(msg.sender, _fee);
}

operator = _identityHash;
operator = _identity;
transferOwnership(operator);
hermes = Hermes(IHermesContract(_hermesId).getOperator(), _hermesId, 0);
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/FundsRecovery.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.4;
pragma solidity 0.7.6;

import { IERC20Token } from "./interfaces/IERC20Token.sol";
import { Ownable } from "./Ownable.sol";
Expand Down
35 changes: 26 additions & 9 deletions contracts/HermesImplementation.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.4;
pragma solidity 0.7.6;

import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
Expand Down Expand Up @@ -70,6 +70,10 @@ contract HermesImplementation is FundsRecovery, Utils {
return keccak256(abi.encodePacked(_identity, address(this)));
}

function getChannelId(address _identity, string memory _type) public view returns (bytes32) {
return keccak256(abi.encodePacked(_identity, address(this), _type));
}

function getRegistry() public view returns (address) {
return address(registry);
}
Expand Down Expand Up @@ -138,6 +142,8 @@ contract HermesImplementation is FundsRecovery, Utils {
// Approving all myst for dex, because MYST token's `transferFrom` is cheaper when there is approval of uint(-1)
token.approve(_dexAddress, uint(-1));
dex = IUniswapV2Router(_dexAddress);

transferOwnership(_operator);
}

function isInitialized() public view returns (bool) {
Expand All @@ -157,7 +163,7 @@ contract HermesImplementation is FundsRecovery, Utils {

// Settle promise
// _preimage is random number generated by receiver used in HTLC
function _settlePromise(bytes32 _channelId, address _beneficiary, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes memory _signature) private returns (uint256) {
function _settlePromise(bytes32 _channelId, address _beneficiary, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes memory _signature, bool _takeFee) private returns (uint256) {
require(
isHermesActive(),
"Hermes: hermes have to be in active state"
Expand Down Expand Up @@ -186,9 +192,9 @@ contract HermesImplementation is FundsRecovery, Utils {
_unpaidAmount = min(_availableBalance, maxStake);
}

_channel.settled = _channel.settled.add(_unpaidAmount); // Increase already paid amount.
uint256 _hermesFee = calculateHermesFee(_unpaidAmount); // Calculate hermes fee.
uint256 _fees = _transactorFee.add(_hermesFee); // Update channel balance.
_channel.settled = _channel.settled.add(_unpaidAmount); // Increase already paid amount.
uint256 _hermesFee = _takeFee ? calculateHermesFee(_unpaidAmount) : 0; // Calculate hermes fee.
uint256 _fees = _transactorFee.add(_hermesFee); // Update channel balance.

// Pay transactor fee
if (_transactorFee > 0) {
Expand All @@ -208,7 +214,18 @@ contract HermesImplementation is FundsRecovery, Utils {

// Settle promise and transfer calculated amount into beneficiary wallet
bytes32 _channelId = getChannelId(_identity);
uint256 _amountToTransfer = _settlePromise(_channelId, _beneficiary, _amount, _transactorFee, _preimage, _signature);
uint256 _amountToTransfer = _settlePromise(_channelId, _beneficiary, _amount, _transactorFee, _preimage, _signature, true);
token.transfer(_beneficiary, _amountToTransfer);
}

function payAndSettle(address _identity, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes memory _signature, address _beneficiary, bytes memory _beneficiarySignature) public {
bytes32 _channelId = getChannelId(_identity, "withdrawal");

// Validate beneficiary to be signed by identity and be attached to given promise
address _signer = keccak256(abi.encodePacked(getChainID(), _channelId, _amount, _preimage, _beneficiary)).recover(_beneficiarySignature);
require(_signer == _identity, "Hermes: payAndSettle request should be properly signed");

uint256 _amountToTransfer = _settlePromise(_channelId, _beneficiary, _amount, _transactorFee, _preimage, _signature, false);
token.transfer(_beneficiary, _amountToTransfer);
}

Expand All @@ -218,7 +235,7 @@ contract HermesImplementation is FundsRecovery, Utils {

// Settle promise and transfer calculated amount into beneficiary wallet
bytes32 _channelId = getChannelId(_identity);
uint256 _amountToTransfer = _settlePromise(_channelId, _newBeneficiary, _amount, _transactorFee, _preimage, _promiseSignature);
uint256 _amountToTransfer = _settlePromise(_channelId, _newBeneficiary, _amount, _transactorFee, _preimage, _promiseSignature, true);
token.transfer(_newBeneficiary, _amountToTransfer);
}

Expand All @@ -228,7 +245,7 @@ contract HermesImplementation is FundsRecovery, Utils {

// Calculate amount to transfer and settle promise
bytes32 _channelId = getChannelId(_identity);
uint256 _amountToTransfer = _settlePromise(_channelId, _beneficiary, _amount, _transactorFee, _preimage, _signature);
uint256 _amountToTransfer = _settlePromise(_channelId, _beneficiary, _amount, _transactorFee, _preimage, _signature, true);

// Transfer funds into beneficiary wallet via DEX
uint amountOutMin = 0;
Expand Down Expand Up @@ -270,7 +287,7 @@ contract HermesImplementation is FundsRecovery, Utils {
// Settlement which will increase channel stake instead of transfering funds into beneficiary wallet.
function settleIntoStake(address _identity, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes memory _signature) public {
bytes32 _channelId = getChannelId(_identity);
uint256 _stakeIncreaseAmount = _settlePromise(_channelId, address(this), _amount, _transactorFee, _preimage, _signature);
uint256 _stakeIncreaseAmount = _settlePromise(_channelId, address(this), _amount, _transactorFee, _preimage, _signature, true);
_increaseStake(_channelId, _stakeIncreaseAmount, true);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/MystToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.4;
pragma solidity 0.7.6;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Context } from "@openzeppelin/contracts/GSN/Context.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/Ownable.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.4;
pragma solidity 0.7.6;

contract Ownable {
address private _owner;
Expand Down
Loading

0 comments on commit 51be353

Please sign in to comment.