Files

206 lines
6.0 KiB
Solidity

pragma solidity =0.7.6;
pragma abicoder v2;
import '../../../../../contracts/test/TestERC20.sol';
import '../../../../../contracts/UniswapV3Pool.sol';
import '../../../../../contracts/UniswapV3Factory.sol';
contract SetupToken {
TestERC20 public token;
constructor() public {
// this contract will receive the total supply of 100 tokens
token = new TestERC20(1e12 ether);
}
function mintTo(address _recipient, uint256 _amount) public {
token.transfer(_recipient, _amount);
}
}
contract SetupTokens {
SetupToken tokenSetup0;
SetupToken tokenSetup1;
TestERC20 public token0;
TestERC20 public token1;
constructor() public {
// create the token wrappers
tokenSetup0 = new SetupToken();
tokenSetup1 = new SetupToken();
// switch them around so that token0's address is lower than token1's
// since this is what the uniswap factory will do when you create the pool
if (address(tokenSetup0.token()) > address(tokenSetup1.token())) {
(tokenSetup0, tokenSetup1) = (tokenSetup1, tokenSetup0);
}
// save the erc20 tokens
token0 = tokenSetup0.token();
token1 = tokenSetup1.token();
}
// mint either token0 or token1 to a chosen account
function mintTo(
uint256 _tokenIdx,
address _recipient,
uint256 _amount
) public {
require(_tokenIdx == 0 || _tokenIdx == 1, 'invalid token idx');
if (_tokenIdx == 0) tokenSetup0.mintTo(_recipient, _amount);
if (_tokenIdx == 1) tokenSetup1.mintTo(_recipient, _amount);
}
}
contract SetupUniswap {
UniswapV3Pool public pool;
TestERC20 token0;
TestERC20 token1;
// will create the following enabled fees and corresponding tickSpacing
// fee 500 + tickSpacing 10
// fee 3000 + tickSpacing 60
// fee 10000 + tickSpacing 200
UniswapV3Factory factory;
constructor(TestERC20 _token0, TestERC20 _token1) public {
factory = new UniswapV3Factory();
token0 = _token0;
token1 = _token1;
}
function createPool(uint24 _fee, uint160 _startPrice) public {
pool = UniswapV3Pool(factory.createPool(address(token0), address(token1), _fee));
pool.initialize(_startPrice);
}
}
contract UniswapMinter {
UniswapV3Pool pool;
TestERC20 token0;
TestERC20 token1;
struct MinterStats {
uint128 liq;
uint128 tL_liqGross;
int128 tL_liqNet;
uint128 tU_liqGross;
int128 tU_liqNet;
}
constructor(TestERC20 _token0, TestERC20 _token1) public {
token0 = _token0;
token1 = _token1;
}
function setPool(UniswapV3Pool _pool) public {
pool = _pool;
}
function uniswapV3MintCallback(
uint256 amount0Owed,
uint256 amount1Owed,
bytes calldata data
) external {
if (amount0Owed > 0) token0.transfer(address(pool), amount0Owed);
if (amount1Owed > 0) token1.transfer(address(pool), amount1Owed);
}
function getTickLiquidityVars(int24 _tickLower, int24 _tickUpper)
internal
view
returns (
uint128,
int128,
uint128,
int128
)
{
(uint128 tL_liqGross, int128 tL_liqNet, , ) = pool.ticks(_tickLower);
(uint128 tU_liqGross, int128 tU_liqNet, , ) = pool.ticks(_tickUpper);
return (tL_liqGross, tL_liqNet, tU_liqGross, tU_liqNet);
}
function getStats(int24 _tickLower, int24 _tickUpper) internal view returns (MinterStats memory stats) {
(uint128 tL_lg, int128 tL_ln, uint128 tU_lg, int128 tU_ln) = getTickLiquidityVars(_tickLower, _tickUpper);
return MinterStats(pool.liquidity(), tL_lg, tL_ln, tU_lg, tU_ln);
}
function doMint(
int24 _tickLower,
int24 _tickUpper,
uint128 _amount
) public returns (MinterStats memory bfre, MinterStats memory aftr) {
bfre = getStats(_tickLower, _tickUpper);
pool.mint(address(this), _tickLower, _tickUpper, _amount, new bytes(0));
aftr = getStats(_tickLower, _tickUpper);
}
function doBurn(
int24 _tickLower,
int24 _tickUpper,
uint128 _amount
) public returns (MinterStats memory bfre, MinterStats memory aftr) {
bfre = getStats(_tickLower, _tickUpper);
pool.burn(_tickLower, _tickUpper, _amount);
aftr = getStats(_tickLower, _tickUpper);
}
}
contract UniswapSwapper {
UniswapV3Pool pool;
TestERC20 token0;
TestERC20 token1;
struct SwapperStats {
uint128 liq;
uint256 feeGrowthGlobal0X128;
uint256 feeGrowthGlobal1X128;
uint256 bal0;
uint256 bal1;
int24 tick;
}
constructor(TestERC20 _token0, TestERC20 _token1) public {
token0 = _token0;
token1 = _token1;
}
function setPool(UniswapV3Pool _pool) public {
pool = _pool;
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external {
if (amount0Delta > 0) token0.transfer(address(pool), uint256(amount0Delta));
if (amount1Delta > 0) token1.transfer(address(pool), uint256(amount1Delta));
}
function getStats() internal view returns (SwapperStats memory stats) {
(, int24 currentTick, , , , , ) = pool.slot0();
return
SwapperStats(
pool.liquidity(),
pool.feeGrowthGlobal0X128(),
pool.feeGrowthGlobal1X128(),
token0.balanceOf(address(this)),
token1.balanceOf(address(this)),
currentTick
);
}
function doSwap(
bool _zeroForOne,
int256 _amountSpecified,
uint160 _sqrtPriceLimitX96
) public returns (SwapperStats memory bfre, SwapperStats memory aftr) {
bfre = getStats();
pool.swap(address(this), _zeroForOne, _amountSpecified, _sqrtPriceLimitX96, new bytes(0));
aftr = getStats();
}
}