Skip to content

Commit

Permalink
feat: Add deployment of SmartKandel Seeder contract in global setup.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxencerb committed May 22, 2024
1 parent 1a85b5a commit aa7cf04
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 11 deletions.
87 changes: 87 additions & 0 deletions src/lib/kandel/distribution.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { parseAbi } from 'viem'
import { expect, it } from 'vitest'
import { describe, inject } from 'vitest'
import { getClient } from '~test/src/client.js'
import { getKandelPositionRawParams } from './params.js'
import { createGeometricDistribution } from './distribution.js'

const { kandelLib, smartKandelSeeder } = inject('kandel')
const { routerProxyFactory, mangrove } = inject('mangrove')
const { wethUSDC } = inject('markets')

const client = getClient()

const kandelLibAbi = parseAbi([
'struct DistributionOffer {uint index;int tick;uint gives;}',
'struct Distribution {DistributionOffer[] asks;DistributionOffer[] bids;}',
'function createGeometricDistribution(uint from,uint to,int baseQuoteTickIndex0,uint _baseQuoteTickOffset,uint firstAskIndex,uint bidGives,uint askGives,uint pricePoints,uint stepSize) external pure returns (Distribution memory distribution)',
])

describe('distribution', () => {
it('checks kandel deployment', async () => {
const [factory, mgv] = await client.multicall({
contracts: [
{
address: smartKandelSeeder,
abi: parseAbi(['function PROXY_FACTORY() view returns (address)']),
functionName: 'PROXY_FACTORY',
},
{
address: smartKandelSeeder,
abi: parseAbi(['function MGV() view returns (address)']),
functionName: 'MGV',
},
],
})
expect(factory.status).toEqual('success')
expect(factory.result).toAddressEqual(routerProxyFactory)
expect(mgv.status).toEqual('success')
expect(mgv.result).toAddressEqual(mangrove)
})

it('checks kandel distribution', async () => {
const params = getKandelPositionRawParams({
minPrice: 2500,
midPrice: 3000,
maxPrice: 3500,
pricePoints: 10n,
market: wethUSDC,
})

const distrib = createGeometricDistribution({
...params,
stepSize: 1n,
market: wethUSDC,
bidGives: 1n,
askGives: 1n,
})

const fromChain = await client.readContract({
address: kandelLib,
abi: kandelLibAbi,
functionName: 'createGeometricDistribution',
args: [
0n,
10n,
params.baseQuoteTickIndex0,
params.baseQuoteTickOffset,
params.firstAskIndex,
1n,
1n,
params.pricePoints,
1n,
],
})

for (let i = 0; i < distrib.asks.length; i++) {
expect(distrib.asks[i].gives).toEqual(fromChain.asks[i].gives)
expect(distrib.asks[i].tick).toEqual(fromChain.asks[i].tick)
expect(distrib.asks[i].index).toEqual(fromChain.asks[i].index)
}
for (let i = 0; i < distrib.bids.length; i++) {
expect(distrib.bids[i].gives).toEqual(fromChain.bids[i].gives)
expect(distrib.bids[i].tick).toEqual(fromChain.bids[i].tick)
expect(distrib.bids[i].index).toEqual(fromChain.bids[i].index)
}
})
})
28 changes: 27 additions & 1 deletion test/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createAnvil, startProxy } from '@viem/anvil'
import { type Address, parseEther, parseUnits } from 'viem'
import { type Address, parseEther, parseUnits, parseAbi } from 'viem'
import { foundry } from 'viem/chains'
import type { GlobalSetupContext } from 'vitest/node'
import type { MarketParams, Token } from '~mgv/index.js'
Expand All @@ -11,10 +11,13 @@ import {
deployMangroveOrder,
deployMangroveReader,
deployRouterProxyFactory,
deploySmartKandel,
openMarket,
setMulticall,
} from './src/contracts/index.js'
import { getMangroveBytecodes } from './src/contracts/mangrove.js'
import { kandellibBytecode } from './src/contracts/kandellib.bytecode.js'
import { smartKandelSeederBytecode } from './src/contracts/smart-kandel-seeder.bytecode.js'

export const multicall: Address = '0xcA11bde05977b3631167028862bE2a173976CA11'

Expand Down Expand Up @@ -60,15 +63,32 @@ export default async function ({ provide }: GlobalSetupContext) {
data.mangroveOrder,
)

const routerImplementation = await globalTestClient.readContract({
address: mangroveOrder,
abi: parseAbi(['function ROUTER_IMPLEMENTATION() view returns (address)']),
functionName: 'ROUTER_IMPLEMENTATION',
})

const { kandelLib, smartKandelSeeder } = await deploySmartKandel(
mangrove,
250_000n,
routerProxyFactory,
routerImplementation,
kandellibBytecode,
smartKandelSeederBytecode,
)

provide('tokens', { WETH, USDC, DAI })
provide('mangrove', {
mangrove,
reader: mangroveReader,
order: mangroveOrder,
routerProxyFactory,
routerImplementation,
multicall,
tickSpacing: 60n,
})
provide('kandel', { kandelLib, smartKandelSeeder })

// open markets

Expand Down Expand Up @@ -112,6 +132,7 @@ export default async function ({ provide }: GlobalSetupContext) {

interface CustomMatchers<R = unknown> {
toApproximateEqual: (expected: number, percentage?: number) => R
toAddressEqual: (expected: Address) => R
}

declare module 'vitest' {
Expand All @@ -128,12 +149,17 @@ declare module 'vitest' {
reader: Address
order: Address
routerProxyFactory: Address
routerImplementation: Address
multicall: Address
tickSpacing: bigint
}
markets: {
wethUSDC: MarketParams
wethDAI: MarketParams
}
kandel: {
kandelLib: Address
smartKandelSeeder: Address
}
}
}
8 changes: 8 additions & 0 deletions test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Address, isAddressEqual } from 'viem'
import { expect } from 'vitest'

expect.extend({
Expand All @@ -19,4 +20,11 @@ expect.extend({
`expected ${received} to be approximately equal to ${expected}`,
}
},

toAddressEqual: (received: Address, expected: Address) => {
return {
pass: isAddressEqual(received, expected),
message: () => `expected ${received} to be equal to ${expected}`,
}
},
})
20 changes: 19 additions & 1 deletion test/src/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,25 @@ export async function deploySmartKandel(
chain: globalTestClient.chain,
bytecode: kandelLibBytecode,
abi: parseAbi(["constructor()"]),
})
} as any)
const libReceipt = await globalTestClient.waitForTransactionReceipt({
hash: libTx,
});
const libAddress = libReceipt.contractAddress;
const seederTx = await globalTestClient.deployContract({
account: globalTestClient.account,
chain: globalTestClient.chain,
bytecode: smartKandelSeederBytecode.replace(/__\$[a-fA-F0-9]{34}\$__/g, libAddress.slice(2)),
abi: parseAbi([
"constructor(address mgv, uint gasreq, address routerProxyFactory, address routerImplementation)",
]),
args: [mgv, kandelGasreq, routerProxyFactory, routerImplementation],
} as any);
const seederReceipt = await globalTestClient.waitForTransactionReceipt({
hash: seederTx,
});
const seederAddress = seederReceipt.contractAddress;
return {kandelLib: libAddress, smartKandelSeeder: seederAddress};
}

export async function deployMangroveCore(bytecode: Hex): Promise<Address> {
Expand Down
9 changes: 0 additions & 9 deletions test/src/contracts/mangrove.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import { Hex } from "viem";
import { join } from "node:path";
import { readFile } from "node:fs/promises";
import { bytecode as mangrove } from "./mangrove.bytecode.js";
import { bytecode as mangroveReader } from "./mgv-reader.bytecode.js";
import { bytecode as mangroveOrder } from "./mgv-order.bytecode.js";
import { bytecode as routerProxyFactory } from "./router-proxy-factory.bytecode.js";

async function readBytecode(src: string): Promise<Hex> {
// return file(join(import.meta.dir, src)).text() as any;
const path = join(import.meta.url, "..", src);
const data = await readFile(path);
return data.toString() as Hex;
}

export async function getMangroveBytecodes() {
return {
mangrove: mangrove as Hex,
Expand Down

0 comments on commit aa7cf04

Please sign in to comment.