Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/eth-no-truffle/PolyWrapper_v1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./libs/lifecycle/Pausable.sol";

import "./interfaces/ILockProxy.sol";

contract PolyWrapper is Ownable, Pausable, ReentrancyGuard {
contract PolyWrapperV1 is Ownable, Pausable, ReentrancyGuard {
using SafeMath for uint;
using SafeERC20 for IERC20;

Expand Down
2 changes: 1 addition & 1 deletion src/eth-no-truffle/PolyWrapper_v2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./libs/lifecycle/Pausable.sol";

import "./interfaces/ILockProxy.sol";

contract PolyWrapper is Ownable, Pausable, ReentrancyGuard {
contract PolyWrapperV2 is Ownable, Pausable, ReentrancyGuard {
using SafeMath for uint;
using SafeERC20 for IERC20;

Expand Down
2 changes: 1 addition & 1 deletion src/eth-no-truffle/PolyWrapper_v3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./libs/lifecycle/Pausable.sol";

import "./interfaces/ILockProxy.sol";

contract PolyWrapper is Ownable, Pausable, ReentrancyGuard {
contract PolyWrapperV3 is Ownable, Pausable, ReentrancyGuard {
using SafeMath for uint;
using SafeERC20 for IERC20;

Expand Down
180 changes: 180 additions & 0 deletions src/eth-no-truffle/PolyWrapper_v4.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.6.0;

import "./libs/token/ERC20/SafeERC20.sol";
import "./libs/token/ERC20/IERC20.sol";
import "./libs/access/Ownable.sol";
import "./libs/utils/ReentrancyGuard.sol";
import "./libs/math/SafeMath.sol";
import "./libs/lifecycle/Pausable.sol";

import "./interfaces/ILockProxy.sol";

contract PolyWrapperV4 is Ownable, Pausable, ReentrancyGuard {
using SafeMath for uint;
using SafeERC20 for IERC20;

uint public maxLockProxyIndex = 0;
uint public chainId;
address public feeCollector;

mapping(uint => address) public lockProxyIndexMap;

constructor(address _owner, uint _chainId) public {
require(_chainId != 0, "!legal");
transferOwnership(_owner);
chainId = _chainId;
}

function setFeeCollector(address collector) external onlyOwner {
require(collector != address(0), "emtpy address");
feeCollector = collector;
}

function resetLockProxy(uint index, address _lockProxy) external onlyOwner {
require(_lockProxy != address(0));
require(lockProxyIndexMap[index] != address(0), "no lockproxy exsist in given index");
lockProxyIndexMap[index] = _lockProxy;
require(ILockProxy(_lockProxy).managerProxyContract() != address(0), "not lockproxy");
}

function addLockProxy(address _lockProxy) external onlyOwner {
require(_lockProxy != address(0));
lockProxyIndexMap[maxLockProxyIndex++] = _lockProxy;
require(ILockProxy(_lockProxy).managerProxyContract() != address(0), "not lockproxy");
}

function pause() external onlyOwner {
_pause();
}

function unpause() external onlyOwner {
_unpause();
}

function extractFee(address token) external {
require(msg.sender == feeCollector, "!feeCollector");
if (token == address(0)) {
payable(msg.sender).transfer(address(this).balance);
} else {
IERC20(token).safeTransfer(feeCollector, IERC20(token).balanceOf(address(this)));
}
}

function lock(address fromAsset, uint64 toChainId, bytes memory toAddress, uint amount, uint fee, uint id) external payable nonReentrant whenNotPaused {

require(toChainId != chainId && toChainId != 0, "!toChainId");
require(toAddress.length !=0, "empty toAddress");
address addr;
assembly { addr := mload(add(toAddress,0x14)) }
require(addr != address(0),"zero toAddress");

_pull(fromAsset, amount);

amount = _checkoutFee(fromAsset, amount, fee);

address lockProxy = _getSupportLockProxy(fromAsset, toChainId);
_push(fromAsset, toChainId, toAddress, amount, lockProxy);

_collectFee();

emit PolyWrapperLock(fromAsset, msg.sender, toChainId, toAddress, amount, fee, id);
}

function specifiedLock(address fromAsset, uint64 toChainId, bytes memory toAddress, uint amount, uint fee, uint id, address lockProxy) external payable nonReentrant whenNotPaused {

require(toChainId != chainId && toChainId != 0, "!toChainId");
require(toAddress.length !=0, "empty toAddress");
address addr;
assembly { addr := mload(add(toAddress,0x14)) }
require(addr != address(0),"zero toAddress");

_pull(fromAsset, amount);

amount = _checkoutFee(fromAsset, amount, fee);

require(isValidLockProxy(lockProxy),"invalid lockProxy");
_push(fromAsset, toChainId, toAddress, amount, lockProxy);

_collectFee();

emit PolyWrapperLock(fromAsset, msg.sender, toChainId, toAddress, amount, fee, id);
}

function speedUp(address fromAsset, bytes memory txHash, uint fee) external payable nonReentrant whenNotPaused {
_pull(fromAsset, fee);
emit PolyWrapperSpeedUp(fromAsset, txHash, msg.sender, fee);
}

function _pull(address fromAsset, uint amount) internal {
if (fromAsset == address(0)) {
require(msg.value == amount, "insufficient ether");
} else {
IERC20(fromAsset).safeTransferFrom(msg.sender, address(this), amount);
}
}

function _collectFee() internal {
if (feeCollector != address(0)) {
payable(feeCollector).transfer(address(this).balance);
}
}

// take fee in the form of ether
function _checkoutFee(address fromAsset, uint amount, uint fee) internal view returns (uint) {
if (fromAsset == address(0)) {
require(msg.value >= amount, "insufficient ether");
require(amount > fee, "amount less than fee");
return amount.sub(fee);
} else {
require(msg.value >= fee, "insufficient ether");
return amount;
}
}

function _push(address fromAsset, uint64 toChainId, bytes memory toAddress, uint amount, address lockProxyAddress) internal {
ILockProxy lockProxy = ILockProxy(lockProxyAddress);
if (fromAsset == address(0)) {
require(lockProxy.lock{value: amount}(fromAsset, toChainId, toAddress, amount), "lock ether fail");
} else {
IERC20(fromAsset).safeApprove(address(lockProxy), 0);
IERC20(fromAsset).safeApprove(address(lockProxy), amount);
require(lockProxy.lock(fromAsset, toChainId, toAddress, amount), "lock erc20 fail");
}
}

function isValidLockProxy(address lockProxy) public view returns(bool) {
for (uint i=0;i<maxLockProxyIndex;i++) {
if (lockProxy == lockProxyIndexMap[i]) {
return true;
}
}
return false;
}

function _getSupportLockProxy(address fromAsset, uint64 toChainId) internal view returns(address) {
for (uint i=0;i<maxLockProxyIndex;i++) {
address lockProxy = lockProxyIndexMap[i];
if (ILockProxy(lockProxy).assetHashMap(fromAsset, toChainId).length != 0) {
return lockProxy;
}
}
revert("No LockProxy Support this cross txn");
}

function getBalanceBatch(address[] memory assets, address richGuy) public view returns(uint[] memory) {
uint[] memory res = new uint[](assets.length);
for (uint i=0;i<assets.length;i++) {
if (assets[i] == address(0)) {
res[i] = richGuy.balance;
} else {
res[i] = IERC20(assets[i]).balanceOf(richGuy);
}
}
return res;
}

event PolyWrapperLock(address indexed fromAsset, address indexed sender, uint64 toChainId, bytes toAddress, uint net, uint fee, uint id);
event PolyWrapperSpeedUp(address indexed fromAsset, bytes indexed txHash, address indexed sender, uint efee);

}