diff --git a/contracts/arbitrum/connectors/uniswap-sell-beta/helpers.sol b/contracts/arbitrum/connectors/uniswap-sell-beta/helpers.sol index c8c7b117..8bc1b65e 100644 --- a/contracts/arbitrum/connectors/uniswap-sell-beta/helpers.sol +++ b/contracts/arbitrum/connectors/uniswap-sell-beta/helpers.sol @@ -12,13 +12,63 @@ contract Helpers { ISwapRouter public constant router = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); - UniswapV3Pool public constant state = - UniswapV3Pool(0x17c14D2c404D167802b16C450d3c99F88F2c4F4d); + bytes32 internal constant POOL_INIT_CODE_HASH = + 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; - function getPriceLimit(uint256 amountIn, bool zeroForOne) - public - returns (uint160) + struct PoolKey { + address token0; + address token1; + uint24 fee; + } + + function getPoolAddress( + address tokenA, + address tokenB, + uint24 fee + ) internal pure returns (address pool) { + if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); + return + computeAddress( + 0x1F98431c8aD98523631AE4a59f267346ea31F984, + PoolKey({token0: tokenA, token1: tokenB, fee: fee}) + ); + } + + function computeAddress(address factory, PoolKey memory key) + internal + pure + returns (address pool) { + require(key.token0 < key.token1); + pool = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256( + abi.encode(key.token0, key.token1, key.fee) + ), + POOL_INIT_CODE_HASH + ) + ) + ) + ) + ); + } + + function getPriceLimit( + uint256 amountIn, + bool zeroForOne, + address tokenA, + address tokenB, + uint24 fee + ) public returns (uint160) { + UniswapV3Pool state = UniswapV3Pool( + getPoolAddress(tokenA, tokenB, fee) + ); + return ( SqrtPriceMath.getNextSqrtPriceFromInput( state.slot0().sqrtPriceX96, @@ -46,7 +96,13 @@ contract Helpers { deadline: block.timestamp + 1, amountIn: amountIn, amountOutMinimum: amountOutMinimum, - sqrtPriceLimitX96: getPriceLimit(amountIn, zeroForOne) + sqrtPriceLimitX96: getPriceLimit( + amountIn, + zeroForOne, + tokenIn, + tokenOut, + fee + ) }); } diff --git a/contracts/arbitrum/connectors/uniswap-sell-beta/libraries/PoolAddress.sol b/contracts/arbitrum/connectors/uniswap-sell-beta/libraries/PoolAddress.sol new file mode 100644 index 00000000..16dfb6e9 --- /dev/null +++ b/contracts/arbitrum/connectors/uniswap-sell-beta/libraries/PoolAddress.sol @@ -0,0 +1,45 @@ +pragma solidity >=0.5.0; + +library PoolAddress { + bytes32 internal constant POOL_INIT_CODE_HASH = + 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; + + struct PoolKey { + address token0; + address token1; + uint24 fee; + } + + function getPoolKey( + address tokenA, + address tokenB, + uint24 fee + ) internal pure returns (PoolKey memory) { + if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); + return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); + } + + function computeAddress(address factory, PoolKey memory key) + internal + pure + returns (address pool) + { + require(key.token0 < key.token1); + pool = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256( + abi.encode(key.token0, key.token1, key.fee) + ), + POOL_INIT_CODE_HASH + ) + ) + ) + ) + ); + } +} diff --git a/test/uniswap-sell-beta/uniswap-sell-beta.js b/test/uniswap-sell-beta/uniswap-sell-beta.js index e161e070..2996cc9c 100644 --- a/test/uniswap-sell-beta/uniswap-sell-beta.js +++ b/test/uniswap-sell-beta/uniswap-sell-beta.js @@ -29,11 +29,38 @@ const WETH_ADDR = "0x82af49447d8a07e3bd95bd0d56f35241523fbab1"; describe("Uniswap-sell-beta", function() { let UniswapSellBeta, uniswapSellBeta; before(async () => { + const account = "0xa067668661c84476afcdc6fa5d758c4c01c34352"; + [owner, add1, add2] = await ethers.getSigners(); + + const tokenArtifact = await artifacts.readArtifact( + "@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20" + ); + const token = new ethers.Contract( + WETH_ADDR, + tokenArtifact.abi, + ethers.provider + ); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [account], + }); + + const signer = await ethers.getSigner(account); + console.log(await token.connect(signer).balanceOf(account)); + await token + .connect(signer) + .transfer(owner.address, ethers.utils.parseUnits("0.00000001", 18)); + + await hre.network.provider.request({ + method: "hardhat_stopImpersonatingAccount", + params: [account], + }); + UniswapSellBeta = await ethers.getContractFactory( "UniswapSellBetaArbitrum" ); uniswapSellBeta = await UniswapSellBeta.deploy(); - [owner, add1, add2] = await ethers.getSigners(); await uniswapSellBeta.deployed(); }); @@ -43,11 +70,11 @@ describe("Uniswap-sell-beta", function() { it("Should Perfrom a swap", async () => { const tx = await uniswapSellBeta.sell( - USDC_ADDR, WETH_ADDR, - ethers.utils.parseUnits("0.000000000001"), + USDC_ADDR, + 3000, ethers.utils.parseUnits("10.0"), - ethers.utils.parseUnits("1.0"), + 0, true ); console.log(tx);