Skip to content

uniswapv3 amm adapter #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 36 commits into from
Closed

Conversation

@snake-poison snake-poison force-pushed the feature/uniswapv3-amm-adapter branch from 45c3327 to 3a0acb8 Compare February 8, 2023 20:16
@snake-poison snake-poison marked this pull request as ready for review February 8, 2023 20:17
@snake-poison
Copy link
Author

Note about checks:

  • ArrakisUniswapV3AmmAdapter.sol#L239 is not covered because recreating the situation in which this would trigger is impractical (creating a mock contract) and unlikely to occur in production.
  • There seem to be integration/forked tests unrelated to this feature that are broken.

Copy link
Collaborator

@ckoopmann ckoopmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looking good. Only some nit-picking regarding the contracts (mostly documentation) as well as some suggestions on how to get the CI green.

@@ -0,0 +1,277 @@
/*
Copyright 2022 Set Labs Inc.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be 2023 and (maybe) Index Coop. No ?

@@ -0,0 +1,83 @@
/*
Copyright 2022 Set Labs Inc.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong date and Copy Right holder. (Should be 2023 IndexCoop no ? )


/**
* @title UniswapV3AmmAdapter
* @author Zishan Sami
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without diminishing Zishans contribution I'd suggest changing this to "Index Coop" as we usually do for all contracts I think.

address setToken = _setToken;
address[] memory components = _components;
uint256[] memory maxTokensIn = _maxTokensIn;
uint256 minLiquidity = _minLiquidity;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we doing these reassignments ? Seems like a waste of gas no ? (For the arrays I suggest just changing the type to "memory" in the call signature if those arrays need to be edited. If they are read only then calldata is cheaper anyway.

address[] memory components = _components;
uint256[] memory minTokensOut = _minTokensOut;
uint256 liquidity = _liquidity;
IArrakisVaultV1 arrakisVaultPool = IArrakisVaultV1(_pool);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Those reassignments seem unnecessary to me

method: "hardhat_reset",
params: [
{
forking: {
Copy link
Collaborator

@ckoopmann ckoopmann Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this hardhat reset is causing the (seemingly unrelated) test failures in the other tests, since this change will persist and therefore lead to the other tests running against a different block.

We have two options here:

  1. Resetting to the state after running these tests to the previously pinned block number.
  2. Adjusting the other tests to work on this block number as well and then updating it for all tests in the hardhat config. I can support here if needed.

I'm a bit conflicted on which is better, but I think long term it might be nice to have different tests running against different block numbers so that we don't have to continously update some of the tests which assume specific market conditions / product states.

Copy link
Collaborator

@ckoopmann ckoopmann Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yet another option to update the blocknumber in hardhat-config and then do this "hardhat_reset" to the old blocknumber for all the test suites that are failing on the new block. I think this is probably the best solution as it should be the individual test suite's "responsibility" to ensure it is running agains the right block if it is sensitive to changes in market conditions / product composition etc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yet another option to update the blocknumber in hardhat-config and then do this "hardhat_reset" to the old blocknumber for all the test suites that are failing on the new block. I think this is probably the best solution as it should be the individual test suite's "responsibility" to ensure it is running agains the right block if it is sensitive to changes in market conditions / product composition etc.

hmm I thought that addSnapshotBeforeRestoreAfterEach would handle setting up a "resetting" to the snapshot after, but maybe its doing the snapshot after the fork which messes things up moving forward. I'll double check my understanding around this flow and likely try to implement this solution.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "before" function is executed before "beforeEach" so the snapshots are probably taken after the fork change and therefore the changed forked block will persist.

I remember having faced similar issues elsewhere though, it could be that the "snapshot" / "restore" rpc calls just don't play well wit the "reset".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great hint towards a solution. I think I can rework the before hook such that from a general level, the network is reset to the fork block for every test as expected.

try IArrakisVaultV1(_pool).token1() returns (address _token1) {
token1 = _token1;
} catch {
return false;
Copy link
Collaborator

@ckoopmann ckoopmann Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why we can't have this line covered, especially since line 234 seems to be covered.

Am I missing anything here ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not that we couldn't, but having a condition where the token0 external call succeeds and the token1 call fails would have to be done with a mock contract that exhibits this behavior.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. That explains why we can cover the first call easily but not the second one.
I still think adding this little mock contract might be worth it if it helps us to just keep it at a nice 100% coverage.
Also might be worth looking into other mock options such as smock ( or whatever the cool kids are using nowadays)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was scared of adding dependencies without upgrading existing dev deps, but I've heard of smock and would love to try it. If I run into an issue with configuring smock, I'll just do a small mock contract to get this to 100% which I agree is nice and why I added a constructor test :)


/**
* Return calldata for the add liquidity call for a single asset
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure all external methods have full docstring documentation including all parameters.

import "../../../interfaces/external/IArrakisVaultV1.sol";

/**
* @title UniswapV3AmmAdapter
Copy link
Collaborator

@ckoopmann ckoopmann Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title should probably be the same as the contract name.


target = router;
value = 0;
data = abi.encodeWithSignature(
Copy link
Collaborator

@ckoopmann ckoopmann Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could do something like:
abi.encodeWithSelector(IArrakis.removeLiquidity.selector ... here no ?

Advantages:

  1. No need of signature string constant
  2. Less error prone
  3. Maybe more efficient if the selector is precomputed at compile time

@pblivin0x pblivin0x closed this Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants