// 交易token,需要输入两种token的量,token要发送到的地址,data用于闪电贷的回调
// this low-level function should be called from a contract which performs important safety checks
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
// 确保至少一个数量大于0
require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
// 获取两种代币的储备量
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
// 确保要有足够的余额
require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{ // scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
// 发送地址不能为这两个token合约
require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
// 发送代币
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
// 如果data有长度,则调用to的接口进行闪电贷
if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
// 获取合约中两种代币的余额
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
// amountIn = balance - (_reserve - amountOut)
// 根据取出的储备量、原有的储备量及最新的余额,反求出输入的金额
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
// 确保输入的金额至少有一个大于0
require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
{ // scope for reserve{0,1}Adjusted, avoids stack too deep errors
// 调整后的余额 = (1 - 0.3%)* 原余额
uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
// 新k值应该大于旧的k值,增加值为手续费
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
}
// 更新储备量
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
contract ChaitinBank {
using SafeMath for uint256;
address public feicoin;
address public owner;
IERC20 public flagToken;
address public chaitinFeifeiTokenPair;
address public chaitinSwap;
uint256 public CTTperFlag;
constructor(address _feicoin, address _owner, address _flagToken, address _chaitinFeifeiTokenPair, address _chaitinSwap, uint256 _CTTperFlag) public {
feicoin = _feicoin;
flagToken = IERC20(_flagToken);
owner = _owner;
chaitinFeifeiTokenPair = _chaitinFeifeiTokenPair;
CTTperFlag = _CTTperFlag;
chaitinSwap = _chaitinSwap;
}
// 计算feicoin与chaitin的相对价格
function calcFeiCoinValue() public view returns(uint256 value){
(uint256 reserve0, uint256 reserve1, uint32 time ) = IPokePair(chaitinFeifeiTokenPair).getReserves(); //TODO:params
address token0 = IPokePair(chaitinFeifeiTokenPair).token0();
if(token0 == feicoin){
value = IPokeRouter01(chaitinSwap).getAmountOut( 10, reserve0, reserve1);
}else{
value = IPokeRouter01(chaitinSwap).getAmountOut( 10, reserve1, reserve0);
}
return value;
}
// Enter the bank. Pay some feifeicoin. Earn some Flags. 用feicoin换flagcoin
function depositFeiCointoFlag(uint256 _amount) public {
// 用户向本合约发送feicoin
IERC20(feicoin).transferFrom(msg.sender, address(this), _amount);
// 计算feicoin与flagcoin的相对价格
uint256 valueOfFeicoin = calcFeiCoinValue(); // exchange feicoin to ChaitinCoin
uint256 exceptFlagsAmount = valueOfFeicoin * ( _amount / 10 ) / CTTperFlag;
uint256 flagsAmount = 0;
if(exceptFlagsAmount <= flagToken.balanceOf(address(this))){
flagsAmount = exceptFlagsAmount;
}else{
flagsAmount = flagToken.balanceOf(address(this));
}
// 向用户发flagtoken
flagToken.transfer(msg.sender, flagsAmount);
}
// Leave the Flags. Claim back your FeiCoins. 用flagcoin换feicoin
function leaveFlagstoFeiCoin(uint256 _amount) public { //TODO: how to define
// 向本合约发送flagcoin
flagToken.transferFrom(msg.sender, address(this), _amount);
uint256 valueOfFeicoin = calcFeiCoinValue();
uint256 exceptFeicoinAmount = _amount * CTTperFlag / valueOfFeicoin;
uint256 feicoinsAmount = 0;
if (exceptFeicoinAmount <= IERC20(feicoin).balanceOf(address(this))){
feicoinsAmount = exceptFeicoinAmount;
}else{
feicoinsAmount = IERC20(feicoin).balanceOf(address(this));
}
IERC20(feicoin).transfer(msg.sender, feicoinsAmount);
}
}
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
require(amount0Out > 0 || amount1Out > 0, 'Chaitin: INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Chaitin: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{ // scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, 'Chaitin: INVALID_TO');
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
if (data.length > 0) IChaitinCallee(to).ChaitinCall(msg.sender, amount0Out, amount1Out, data);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'Chaitin: INSUFFICIENT_INPUT_AMOUNT');
{ // scope for reserve{0,1}Adjusted, avoids stack too deep errors
uint balance0Adjusted = balance0.mul(10000).sub(amount0In.mul(25));
uint balance1Adjusted = balance1.mul(10000).sub(amount1In.mul(25));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'Chaitin: K');
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
uint balance0Adjusted = balance0.mul(10000).sub(amount0In.mul(25));
uint balance1Adjusted = balance1.mul(10000).sub(amount1In.mul(25));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_rserve0).mul(_reserve1).mul(1000**2), 'Chaitin: K');
这将导致什么后果呢?正常情况下,对换之前应满足:
对换之后应满足:
但由于k值变为了原来的1%,现在只需满足:
换出来的y为:
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = ChaitinLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'ChaitinRouter: EXCESSIVE_INPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0], msg.sender, ChaitinLibrary.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
还没有评论,来说两句吧...