-
Notifications
You must be signed in to change notification settings - Fork 270
test partial fill #114
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
base: main
Are you sure you want to change the base?
test partial fill #114
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ import { | |
| getAdvancedOrderParams, | ||
| AdvancedOrder, | ||
| Order, | ||
| defaultAvailableAdvancedOrders, | ||
| } from './shared/protocolHelpers/seaport' | ||
| import { resetFork, WETH, DAI } from './shared/mainnetForkHelpers' | ||
| import { CommandType, RoutePlanner } from './shared/planner' | ||
|
|
@@ -197,14 +198,112 @@ describe('Router', () => { | |
| [DAI.address, WETH.address], | ||
| router.address, | ||
| ]) | ||
| planner.addCommand(CommandType.UNWRAP_WETH, [alice.address, value]) | ||
| planner.addCommand(CommandType.UNWRAP_WETH, [router.address, value]) | ||
| planner.addCommand(CommandType.SEAPORT, [value.toString(), calldata]) | ||
| const { commands, inputs } = planner | ||
| const covenBalanceBefore = await covenContract.balanceOf(alice.address) | ||
| await router['execute(bytes,bytes[],uint256)'](commands, inputs, DEADLINE, { value }) | ||
| await router['execute(bytes,bytes[],uint256)'](commands, inputs, DEADLINE) | ||
| const covenBalanceAfter = await covenContract.balanceOf(alice.address) | ||
| expect(covenBalanceAfter.sub(covenBalanceBefore)).to.eq(1) | ||
| }) | ||
|
|
||
| it('completes a trade for ERC20 --> ETH --> NFTs, invalid Seaport order', async () => { | ||
snreynolds marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const maxAmountIn = expandTo18DecimalsBN(100_000) | ||
| // in this case there is leftover dai in the router, and the unspent eth gets sent to alice | ||
| await daiContract.transfer(router.address, maxAmountIn) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should now use permit2 to transfer in the tokens 👯
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can just add a so that then during v2 it can pull in the tokens from the user :) |
||
|
|
||
| let invalidSeaportOrder = JSON.parse(JSON.stringify(seaportOrders[0])) | ||
| const { order: seaportOrder, value: seaportValue } = getOrderParams(invalidSeaportOrder) | ||
| let nftxValue: BigNumber = expandTo18DecimalsBN(4) | ||
| let totalValue = seaportValue.add(nftxValue) | ||
|
|
||
| // invalidate Seaport order | ||
| invalidSeaportOrder.protocol_data.signature = '0xdeadbeef' | ||
| const calldataOpensea = seaportInterface.encodeFunctionData('fulfillOrder', [seaportOrder, OPENSEA_CONDUIT_KEY]) | ||
|
|
||
| // valid NFTX order | ||
| let numCovensNFTX = 2 | ||
| const calldataNFTX = nftxZapInterface.encodeFunctionData('buyAndRedeem', [ | ||
| NFTX_COVEN_VAULT_ID, | ||
| numCovensNFTX, | ||
| [], | ||
| [WETH.address, NFTX_COVEN_VAULT], | ||
| alice.address, | ||
| ]) | ||
|
|
||
| planner.addCommand(CommandType.V2_SWAP_EXACT_OUT, [ | ||
| totalValue, | ||
| maxAmountIn, | ||
| [DAI.address, WETH.address], | ||
| router.address, | ||
| ]) | ||
| planner.addCommand(CommandType.UNWRAP_WETH, [router.address, totalValue]) | ||
| planner.addCommand(CommandType.SEAPORT, [seaportValue.toString(), calldataOpensea], true) | ||
|
|
||
| planner.addCommand(CommandType.NFTX, [nftxValue, calldataNFTX]) | ||
|
|
||
| const { commands, inputs } = planner | ||
|
|
||
| const routerEthBalanceBefore = await ethers.provider.getBalance(router.address) | ||
| const covenBalanceBefore = await covenContract.balanceOf(alice.address) | ||
|
|
||
| await router['execute(bytes,bytes[],uint256)'](commands, inputs, DEADLINE) | ||
|
|
||
| const covenBalanceAfter = await covenContract.balanceOf(alice.address) | ||
| const routerEthBalanceAfter = await ethers.provider.getBalance(router.address) | ||
|
|
||
| expect(covenBalanceAfter.sub(covenBalanceBefore)).to.eq(numCovensNFTX) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to make sure that the user gets their money back for the NFT's they did not receive |
||
| expect(routerEthBalanceAfter).to.eq(routerEthBalanceBefore) | ||
| }) | ||
|
|
||
| it('completes a trade for ERC20 --> ETH --> NFTs with Seaport, fulfillAvailableAdvancedOrders fill', async () => { | ||
| const maxAmountIn = expandTo18DecimalsBN(100_000) | ||
| // in this case there is leftover dai in the router and all eth gets spent on the nfts | ||
| await daiContract.transfer(router.address, maxAmountIn) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. aaand again |
||
|
|
||
| const { advancedOrder: advancedOrder0, value: value1 } = getAdvancedOrderParams(seaportOrders[0]) | ||
| const { advancedOrder: advancedOrder1, value: value2 } = getAdvancedOrderParams(seaportOrders[1]) | ||
| const params0 = advancedOrder0.parameters | ||
| const params1 = advancedOrder1.parameters | ||
| const totalValue = value1.add(value2) | ||
|
|
||
| const calldata = defaultAvailableAdvancedOrders(alice.address, advancedOrder0, advancedOrder1) | ||
|
|
||
| planner.addCommand(CommandType.V2_SWAP_EXACT_OUT, [ | ||
| totalValue, | ||
| maxAmountIn, | ||
| [DAI.address, WETH.address], | ||
| router.address, | ||
| ]) | ||
| planner.addCommand(CommandType.UNWRAP_WETH, [router.address, totalValue]) | ||
|
|
||
| planner.addCommand(CommandType.SEAPORT, [totalValue, calldata]) | ||
| const { commands, inputs } = planner | ||
|
|
||
| const nftId0 = params0.offer[0].identifierOrCriteria | ||
| const nftId1 = params1.offer[0].identifierOrCriteria | ||
|
|
||
| const owner0Before = await covenContract.ownerOf(nftId0) | ||
| const owner1Before = await covenContract.ownerOf(nftId1) | ||
| const ethBefore = await ethers.provider.getBalance(alice.address) | ||
| const routerEthBalanceBefore = await ethers.provider.getBalance(router.address) | ||
|
|
||
| const receipt = await (await router['execute(bytes,bytes[],uint256)'](commands, inputs, DEADLINE)).wait() | ||
|
|
||
| const owner0After = await covenContract.ownerOf(nftId0) | ||
| const owner1After = await covenContract.ownerOf(nftId1) | ||
| const ethAfter = await ethers.provider.getBalance(alice.address) | ||
| const routerEthBalanceAfter = await ethers.provider.getBalance(router.address) | ||
| const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice) | ||
| const ethDelta = ethBefore.sub(ethAfter) | ||
|
|
||
| expect(owner0Before.toLowerCase()).to.eq(params0.offerer) | ||
| expect(owner1Before.toLowerCase()).to.eq(params1.offerer) | ||
| expect(owner0After).to.eq(alice.address) | ||
| expect(owner1After).to.eq(alice.address) | ||
| expect(ethDelta).to.eq(gasSpent) // eth spent only on gas bc trade came from DAI | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if this was a partial fill, does some ether get stuck in the router?? might be good to check that router balance is 0 and that Alice got refunded for her partial fill....I may have forgetten to do this in my other partial fill tests. 😬 |
||
| expect(routerEthBalanceBefore).to.eq(routerEthBalanceAfter) // ensure no eth is left in the router | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.