329 lines
7.6 KiB
Solidity
329 lines
7.6 KiB
Solidity
/*
|
|
|
|
Copyright 2019 ZeroEx Intl.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
pragma solidity ^0.5.9;
|
|
pragma experimental ABIEncoderV2;
|
|
|
|
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
|
import "../src/bridges/KyberBridge.sol";
|
|
import "../src/interfaces/IKyberNetworkProxy.sol";
|
|
|
|
|
|
// solhint-disable no-simple-event-func-name
|
|
interface ITestContract {
|
|
|
|
function wethWithdraw(
|
|
address payable ownerAddress,
|
|
uint256 amount
|
|
)
|
|
external;
|
|
|
|
function wethDeposit(
|
|
address ownerAddress
|
|
)
|
|
external
|
|
payable;
|
|
|
|
function tokenTransfer(
|
|
address ownerAddress,
|
|
address recipientAddress,
|
|
uint256 amount
|
|
)
|
|
external
|
|
returns (bool success);
|
|
|
|
function tokenApprove(
|
|
address ownerAddress,
|
|
address spenderAddress,
|
|
uint256 allowance
|
|
)
|
|
external
|
|
returns (bool success);
|
|
|
|
function tokenBalanceOf(
|
|
address ownerAddress
|
|
)
|
|
external
|
|
view
|
|
returns (uint256 balance);
|
|
}
|
|
|
|
|
|
/// @dev A minimalist ERC20/WETH token.
|
|
contract TestToken {
|
|
|
|
uint8 public decimals;
|
|
ITestContract private _testContract;
|
|
|
|
constructor(uint8 decimals_) public {
|
|
decimals = decimals_;
|
|
_testContract = ITestContract(msg.sender);
|
|
}
|
|
|
|
function approve(address spender, uint256 allowance)
|
|
external
|
|
returns (bool)
|
|
{
|
|
return _testContract.tokenApprove(
|
|
msg.sender,
|
|
spender,
|
|
allowance
|
|
);
|
|
}
|
|
|
|
function transfer(address recipient, uint256 amount)
|
|
external
|
|
returns (bool)
|
|
{
|
|
return _testContract.tokenTransfer(
|
|
msg.sender,
|
|
recipient,
|
|
amount
|
|
);
|
|
}
|
|
|
|
function withdraw(uint256 amount)
|
|
external
|
|
{
|
|
return _testContract.wethWithdraw(msg.sender, amount);
|
|
}
|
|
|
|
function deposit()
|
|
external
|
|
payable
|
|
{
|
|
return _testContract.wethDeposit.value(msg.value)(msg.sender);
|
|
}
|
|
|
|
function allowance(address, address) external view returns (uint256) {
|
|
return 0;
|
|
}
|
|
|
|
function balanceOf(address owner)
|
|
external
|
|
view
|
|
returns (uint256)
|
|
{
|
|
return _testContract.tokenBalanceOf(owner);
|
|
}
|
|
}
|
|
|
|
|
|
/// @dev KyberBridge overridden to mock tokens and implement IKyberBridge.
|
|
contract TestKyberBridge is
|
|
KyberBridge,
|
|
ITestContract,
|
|
IKyberNetworkProxy
|
|
{
|
|
event KyberBridgeTrade(
|
|
uint256 msgValue,
|
|
address sellTokenAddress,
|
|
uint256 sellAmount,
|
|
address buyTokenAddress,
|
|
address payable recipientAddress,
|
|
uint256 maxBuyTokenAmount,
|
|
uint256 minConversionRate,
|
|
address walletId
|
|
);
|
|
|
|
event KyberBridgeWethWithdraw(
|
|
address ownerAddress,
|
|
uint256 amount
|
|
);
|
|
|
|
event KyberBridgeWethDeposit(
|
|
uint256 msgValue,
|
|
address ownerAddress,
|
|
uint256 amount
|
|
);
|
|
|
|
event KyberBridgeTokenApprove(
|
|
address tokenAddress,
|
|
address ownerAddress,
|
|
address spenderAddress,
|
|
uint256 allowance
|
|
);
|
|
|
|
event KyberBridgeTokenTransfer(
|
|
address tokenAddress,
|
|
address ownerAddress,
|
|
address recipientAddress,
|
|
uint256 amount
|
|
);
|
|
|
|
IEtherToken public weth;
|
|
mapping (address => mapping (address => uint256)) private _tokenBalances;
|
|
uint256 private _nextFillAmount;
|
|
|
|
constructor() public {
|
|
weth = IEtherToken(address(new TestToken(18)));
|
|
}
|
|
|
|
/// @dev Implementation of `IKyberNetworkProxy.trade()`
|
|
function trade(
|
|
address sellTokenAddress,
|
|
uint256 sellAmount,
|
|
address buyTokenAddress,
|
|
address payable recipientAddress,
|
|
uint256 maxBuyTokenAmount,
|
|
uint256 minConversionRate,
|
|
address walletId
|
|
)
|
|
external
|
|
payable
|
|
returns(uint256 boughtAmount)
|
|
{
|
|
emit KyberBridgeTrade(
|
|
msg.value,
|
|
sellTokenAddress,
|
|
sellAmount,
|
|
buyTokenAddress,
|
|
recipientAddress,
|
|
maxBuyTokenAmount,
|
|
minConversionRate,
|
|
walletId
|
|
);
|
|
return _nextFillAmount;
|
|
}
|
|
|
|
function createToken(uint8 decimals)
|
|
external
|
|
returns (address tokenAddress)
|
|
{
|
|
return address(new TestToken(decimals));
|
|
}
|
|
|
|
function setNextFillAmount(uint256 amount)
|
|
external
|
|
payable
|
|
{
|
|
if (msg.value != 0) {
|
|
require(amount == msg.value, "VALUE_AMOUNT_MISMATCH");
|
|
grantTokensTo(address(weth), address(this), msg.value);
|
|
}
|
|
_nextFillAmount = amount;
|
|
}
|
|
|
|
function wethDeposit(
|
|
address ownerAddress
|
|
)
|
|
external
|
|
payable
|
|
{
|
|
require(msg.sender == address(weth), "ONLY_WETH");
|
|
grantTokensTo(address(weth), ownerAddress, msg.value);
|
|
emit KyberBridgeWethDeposit(
|
|
msg.value,
|
|
ownerAddress,
|
|
msg.value
|
|
);
|
|
}
|
|
|
|
function wethWithdraw(
|
|
address payable ownerAddress,
|
|
uint256 amount
|
|
)
|
|
external
|
|
{
|
|
require(msg.sender == address(weth), "ONLY_WETH");
|
|
_tokenBalances[address(weth)][ownerAddress] -= amount;
|
|
ownerAddress.transfer(amount);
|
|
emit KyberBridgeWethWithdraw(
|
|
ownerAddress,
|
|
amount
|
|
);
|
|
}
|
|
|
|
function tokenApprove(
|
|
address ownerAddress,
|
|
address spenderAddress,
|
|
uint256 allowance
|
|
)
|
|
external
|
|
returns (bool success)
|
|
{
|
|
emit KyberBridgeTokenApprove(
|
|
msg.sender,
|
|
ownerAddress,
|
|
spenderAddress,
|
|
allowance
|
|
);
|
|
return true;
|
|
}
|
|
|
|
function tokenTransfer(
|
|
address ownerAddress,
|
|
address recipientAddress,
|
|
uint256 amount
|
|
)
|
|
external
|
|
returns (bool success)
|
|
{
|
|
_tokenBalances[msg.sender][ownerAddress] -= amount;
|
|
_tokenBalances[msg.sender][recipientAddress] += amount;
|
|
emit KyberBridgeTokenTransfer(
|
|
msg.sender,
|
|
ownerAddress,
|
|
recipientAddress,
|
|
amount
|
|
);
|
|
return true;
|
|
}
|
|
|
|
function tokenBalanceOf(
|
|
address ownerAddress
|
|
)
|
|
external
|
|
view
|
|
returns (uint256 balance)
|
|
{
|
|
return _tokenBalances[msg.sender][ownerAddress];
|
|
}
|
|
|
|
function grantTokensTo(address tokenAddress, address ownerAddress, uint256 amount)
|
|
public
|
|
payable
|
|
{
|
|
_tokenBalances[tokenAddress][ownerAddress] += amount;
|
|
if (tokenAddress != address(weth)) {
|
|
// Send back ether if not WETH.
|
|
msg.sender.transfer(msg.value);
|
|
} else {
|
|
require(msg.value == amount, "VALUE_AMOUNT_MISMATCH");
|
|
}
|
|
}
|
|
|
|
// @dev overridden to point to this contract.
|
|
function _getKyberNetworkProxyAddress()
|
|
internal
|
|
view
|
|
returns (address)
|
|
{
|
|
return address(this);
|
|
}
|
|
|
|
// @dev overridden to point to test WETH.
|
|
function _getWethAddress()
|
|
internal
|
|
view
|
|
returns (address)
|
|
{
|
|
return address(weth);
|
|
}
|
|
}
|