-
Notifications
You must be signed in to change notification settings - Fork 465
🔂 Liquidity Provider Asset Swapper integration #2505
Conversation
…new contracts and their respective interfaces
…eature/plp-integration # Conflicts: # packages/asset-swapper/package.json
I have a review: the circleci says: Failure due to missing or extra semicolons in various places on the first static-tests check screen of fail? |
and this one test-rest another review: You are missing a {} says the interpreter error? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we exporting DummyLiquidityProvider and DummyLiquidityProviderRegistry in @0x/contract-wrappers
and @0x/contract-artifacts
? We should avoid doing so if possible
returns (uint256 makerTokenAmount) { | ||
makerTokenAmount = sellAmount - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit:
returns (uint256 makerTokenAmount) { | |
makerTokenAmount = sellAmount - 1; | |
returns (uint256 makerTokenAmount) | |
{ | |
makerTokenAmount = sellAmount - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
returns (uint256 takerTokenAmount) { | ||
takerTokenAmount = buyAmount + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
address takerToken, | ||
address makerToken, | ||
address poolAddress | ||
) external |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
) external | |
) | |
external |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
constructor() | ||
public | ||
// solhint-disable-next-line no-empty-blocks | ||
{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no constructor needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
constructor() | ||
public | ||
// solhint-disable-next-line no-empty-blocks | ||
{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no constructor needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
expect(sellQuotes.length).to.eql(1); | ||
const iquidityPoolSellQuotes: DexSample[] = sellQuotes[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const iquidityPoolSellQuotes: DexSample[] = sellQuotes[0]; | |
const liquidityPoolSellQuotes: DexSample[] = sellQuotes[0]; |
@@ -141,6 +141,7 @@ describe('MarketOperationUtils tests', () => { | |||
makerToken: string, | |||
takerToken: string, | |||
fillAmounts: BigNumber[], | |||
liquidityProviderAddress?: string | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The | undefined
is redundant with the ?
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed! thanks
@@ -172,14 +195,47 @@ describe('MarketOperationUtils tests', () => { | |||
makerToken: string, | |||
takerToken: string, | |||
fillAmounts: BigNumber[], | |||
liquidityProviderAddress?: string | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed! thanks
const yAsset = randomAddress(); | ||
const toSell = Web3Wrapper.toBaseUnitAmount(10, 18); | ||
|
||
const [getSellQuiotesParams, getSellQuotesFn] = callTradeOperationAndRetainLiquidityProviderParams( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const [getSellQuiotesParams, getSellQuotesFn] = callTradeOperationAndRetainLiquidityProviderParams( | |
const [getSellQuotesParams, getSellQuotesFn] = callTradeOperationAndRetainLiquidityProviderParams( |
getLiquidityProviderFn, | ||
] = getLiquidityProviderFromRegistryAndReturnCallParameters(liquidityPoolAddress); | ||
replaceSamplerOps({ | ||
getOrderFillableTakerAmounts: () => [new BigNumber(0)], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getOrderFillableTakerAmounts: () => [new BigNumber(0)], | |
getOrderFillableTakerAmounts: () => [constants.ZERO_AMOUNT], |
@@ -130,6 +146,7 @@ export class MarketOperationUtils { | |||
makerToken, | |||
collapsePath(optimalPath, false), | |||
_opts.bridgeSlippage, | |||
liquidityPoolAddress, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit - liquidityPool
-> liquidityProvider
private _createBuyOrdersPathFromSamplerResultIfExists( | ||
nativeOrders: SignedOrder[], | ||
makerAmount: BigNumber, | ||
nativeOrderFillableAmounts: BigNumber[], | ||
dexQuotes: DexSample[][], | ||
ethToTakerAssetRate: BigNumber, | ||
opts: GetMarketOrdersOpts, | ||
liquidityPoolAddress?: string | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit - liquidityPool
-> liquidityProvider
packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts
Show resolved
Hide resolved
/// selling `sellAmount` of `takerToken`. | ||
/// @param sellAmount Amount of `takerToken` to sell. | ||
/// @return makerTokenAmount Amount of `makerToken` that would be obtained. | ||
function getSellQuote( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified that this matches the spec ✅
/// order to obtain `buyAmount` of `makerToken`. | ||
/// @param buyAmount Amount of `makerToken` to buy. | ||
/// @return takerTokenAmount Amount of `takerToken` that would need to be sold. | ||
function getBuyQuote( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified that this matches the spec ✅
/// @param makerToken Second asset managed by pool. | ||
/// @param poolAddress Address of pool. | ||
function setLiquidityProviderForMarket( | ||
address takerToken, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit - this naming may be confusing because either asset could be the taker/maker token on a given trade. Something like xToken
/ yToken
or firstToken
/ secondToken
may be better 🤷♂.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Verified the Solidity against the spec and it looks good. It could be good for an engineer more familiar with Asset Swapper to give this a review as well.
…eature/plp-integration # Conflicts: # packages/asset-swapper/package.json # packages/asset-swapper/src/utils/market_operation_utils/sampler.ts # packages/asset-swapper/src/utils/market_operation_utils/types.ts # packages/asset-swapper/test/market_operation_utils_test.ts
view | ||
returns (uint256 makerTokenAmount) | ||
{ | ||
makerTokenAmount = sellAmount - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be good to use LibSafeMath
here and below to avoid wonky output in future testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job wrangling this nightmare-level codebase! Just some (small?) requests.
@@ -0,0 +1,346 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We never used to expose this contract before. Why now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exposing this contract allows me to deploy it on-chain (Ganache) and perform E2E simulations of sampling PLP liquidity
takerToken: string, | ||
makerToken: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we flip the order of these? Just to be consistent with the other ops. I know it's the other way in the contract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
takerToken: string, | ||
makerToken: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
takerToken: string, | ||
makerToken: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -326,6 +341,104 @@ describe('DexSampler tests', () => { | |||
); | |||
expect(quotes).to.deep.eq(expectedQuotes); | |||
}); | |||
|
|||
describe('LiquidityProvider Operations', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how I feel about these tests. These seem be partially testing the test contracts. I'd also rather we didn't do on-chain tests in this package.
Do you want to unit test the DexOrderSampler
ops? If so, extending the MockSamplerContract
is the way to go, like how the other tests in this file do it. This would also remove the need for the new test contracts.
But if you want to unit test ERC20BridgeSampler
integration with liquidity providers, that should be done in the contracts/erc20-bridge-sampler
package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's a wise point of view, I'm going to move my tests in erc20-bridge-sampler
test package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored and moved those unit tests to erc20-bridge-sampler
. I also added extra unit tests using MockSamplerContract
const liquidityProviderAddress = randomAddress(); | ||
const xAsset = randomAddress(); | ||
const yAsset = randomAddress(); | ||
const toSell = Web3Wrapper.toBaseUnitAmount(10, 18); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: There's a better version of this in @0x/utils
(fromTokenUnitAmount()
, toTokenUnitAmount()
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I didn't know about this utility :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
const toSell = Web3Wrapper.toBaseUnitAmount(10, 18); | ||
|
||
const [getSellQuotesParams, getSellQuotesFn] = callTradeOperationAndRetainLiquidityProviderParams( | ||
createGetMultipleSellQuotesOperationFromRates, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels like this whole test case should be with the "sell" test cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, my bad. Fixing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
ORDER_DOMAIN, | ||
registryAddress, | ||
); | ||
const result = await sampler.getMarketSellOrdersAsync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, definitely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, my bad. Fixing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
…eature/plp-integration # Conflicts: # packages/contract-addresses/addresses.json # packages/contract-wrappers/package.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Easy changes then all good! Fantastic job!
@@ -31,7 +31,7 @@ | |||
"wrappers:generate": "abi-gen --abis ${npm_package_config_abis} --output src/generated-wrappers --backend ethers" | |||
}, | |||
"config": { | |||
"abis": "../contract-artifacts/artifacts/@(DevUtils|ERC20Token|ERC721Token|Exchange|Forwarder|IAssetData|LibTransactionDecoder|WETH9|Coordinator|Staking|StakingProxy|IERC20BridgeSampler|ERC20BridgeSampler|GodsUnchainedValidator|Broker|ILiquidityProvider|ILiquidityProviderRegistry|DummyLiquidityProvider|DummyLiquidityProviderRegistry).json" | |||
"abis": "../contract-artifacts/artifacts/@(DevUtils|ERC20Token|ERC721Token|Exchange|Forwarder|IAssetData|LibTransactionDecoder|WETH9|Coordinator|Staking|StakingProxy|IERC20BridgeSampler|ERC20BridgeSampler|GodsUnchainedValidator|Broker|ILiquidityProvider|ILiquidityProviderRegistry|DummyLiquidityProvider|DummyLiquidityProviderRegistry|MaximumGasPrice).json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make sure there are no Dummy*
contracts exported by this package? No one would use them outside of tests. If they want them, they can import them directly from the erc20-bridge-sampler
package.
@@ -716,6 +718,93 @@ blockchainTests('erc20-bridge-sampler', env => { | |||
}); | |||
}); | |||
|
|||
blockchainTests.resets('getLiquidityProviderFromRegistry', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: All the test cases here are constant, so no chain state to reset. This can just be a regular describe()
block.
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync() | ||
.txHashPromise; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to call createTokenExchanges
. It just creates uniswap exchanges, which you aren't using.
); | ||
await registryContract | ||
.setLiquidityProviderForMarket(xAsset, yAsset, liquidityProvider.address) | ||
.awaitTransactionSuccessAsync().txHashPromise; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.awaitTransactionSuccessAsync().txHashPromise; | |
.awaitTransactionSuccessAsync(); |
@@ -10,6 +10,8 @@ import { Order } from '@0x/types'; | |||
import { BigNumber, hexUtils } from '@0x/utils'; | |||
import * as _ from 'lodash'; | |||
|
|||
import { DummyLiquidityProviderContract, DummyLiquidityProviderRegistryContract } from '../src'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can pull these in from './wrappers'
.
Description
This PR contains the implementation of "liquidity providers". This new feature allows third-party developers to plug in their own private liquidity sources that adhere to the
IERC20Bridge.bridgeTransferFrom()
interface.Testing instructions
Tested using a mocked liquidity provider, unit tests, and more testing to come!
Types of changes
Checklist:
[WIP]
if necessary.