Skip to content

Commit

Permalink
fix: correct withdrawal fee calculation to take into acc when cashAft…
Browse files Browse the repository at this point in the history
…er is negative
  • Loading branch information
MrBeaverTail committed Nov 9, 2023
1 parent ac3c5dd commit e8f931a
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 2 deletions.
14 changes: 12 additions & 2 deletions contracts/pool/Core.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,27 @@ contract Core {
}

uint256 cashAfter;
// reverse is true when cashAfter is a negative number
bool reverse;
// Cover case where cash <= amount
if (cash > amount) {
cashAfter = cash - amount;
} else {
cashAfter = 0;
cashAfter = amount - cash;
reverse = true;
}

uint256 covAfter = (cashAfter).wdiv(liability - amount);
uint256 slippageBefore = _slippageFunc(k, n, c1, xThreshold, covBefore);
uint256 slippageAfter = _slippageFunc(k, n, c1, xThreshold, covAfter);
uint256 slippageNeutral = _slippageFunc(k, n, c1, xThreshold, WAD); // slippage on cov = 1
uint256 slippageAfter;

// in case cashAfter is a negative number, we use slippageAfter = c1 + covAfter
if (reverse) {
slippageAfter = c1 + covAfter;
} else {
slippageAfter = _slippageFunc(k, n, c1, xThreshold, covAfter);
}

// calculate fee
// fee = a - b
Expand Down
21 changes: 21 additions & 0 deletions test/helpers/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,27 @@ export const setupSAvaxPool = async (owner: Signer): Promise<{ pool: Contract; W
return { pool, WETH }
}

export const setupSAvaxPoolTestERC20 = async (owner: Signer): Promise<{ pool: Contract; WETH: Contract }> => {
PoolYYAvax = await ethers.getContractFactory('PoolSAvax')
WETHForwarder = await ethers.getContractFactory('WETHForwarder')

const pool = await PoolYYAvax.connect(owner).deploy()
const WETH = await TestERC20.connect(owner).deploy('WAVAX', 'WAVAX', 18, parseEther('10000000000000000000000'))

// Wait for contract to be deployed
await pool.deployTransaction.wait()
await WETH.deployTransaction.wait()

await pool.connect(owner).initialize(WETH.address)

// Set WETH Forwarder
const forwarder = await WETHForwarder.connect(owner).deploy(WETH.address)
await forwarder.connect(owner).setPool(pool.address)
await pool.connect(owner).setWETHForwarder(forwarder.address)

return { pool, WETH }
}

export const setupYYAvaxPool = async (owner: Signer): Promise<{ pool: Contract; WETH: Contract }> => {
PoolYYAvax = await ethers.getContractFactory('PoolYYAvax')
WETHForwarder = await ethers.getContractFactory('WETHForwarder')
Expand Down
112 changes: 112 additions & 0 deletions test/pool-savax/PoolAvax.arb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { ethers } from 'hardhat'
import { parseEther } from '@ethersproject/units'
import chai from 'chai'
import { solidity } from 'ethereum-waffle'
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { BigNumber, constants, ContractFactory } from 'ethers'
import {
createAndInitializeToken,
fundUserAndApprovePool,
expectAssetValues,
setupAggregateAccount,
setupSAvaxPoolTestERC20,
setupSAvaxPriceFeed,
} from '../helpers/helper'

const { expect } = chai
chai.use(solidity)

describe('AvaxPool Arb', function () {
let owner: SignerWithAddress
let users: SignerWithAddress[]
let TestERC20: ContractFactory
let Asset: ContractFactory

before(async () => {
const [first, ...rest] = await ethers.getSigners()
owner = first
users = rest

TestERC20 = await ethers.getContractFactory('TestERC20')
Asset = await ethers.getContractFactory('Asset')
})

beforeEach(async function () {
this.lastBlock = await ethers.provider.getBlock('latest')
this.lastBlockTime = this.lastBlock.timestamp
this.fiveSecondsSince = this.lastBlockTime + 5 * 1000
this.fiveSecondsAgo = this.lastBlockTime - 5 * 1000

// avax pool
const poolSetup = await setupSAvaxPoolTestERC20(owner)
this.pool = poolSetup.pool
this.WETH = poolSetup.WETH

await setupSAvaxPriceFeed(this.pool)
})

describe('Arb pool', function () {
beforeEach(async function () {
const aggregateName = 'Liquid staking AVAX Aggregate'
const aggregateAccount = await setupAggregateAccount(owner, aggregateName, true)
await aggregateAccount.deployTransaction.wait()

this.assetAVAX = await Asset.connect(owner).deploy()
await this.assetAVAX
.connect(owner)
.initialize(this.WETH.address, 'AVAX Asset', 'LP-AVAX', aggregateAccount.address)
await this.assetAVAX.connect(owner).setPool(this.pool.address)
await this.pool.connect(owner).addAsset(this.WETH.address, this.assetAVAX.address)

const tokenSetSAvax = await createAndInitializeToken('sAVAX', 18, owner, this.pool, aggregateAccount)

this.sAVAX = tokenSetSAvax.token
this.assetSAVAX = tokenSetSAvax.asset

await this.pool.setSAvax(this.sAVAX.address)

await fundUserAndApprovePool(this.sAVAX, owner, parseEther('100000000000').toString(), this.pool, owner)
await fundUserAndApprovePool(this.WETH, owner, parseEther('100000000000').toString(), this.pool, owner)

// SAVAX SETUP
const sAvaxCash = parseEther('1478053.383')
const sAvaxLiability = parseEther('747812.6418')

await this.pool.deposit(this.sAVAX.address, sAvaxLiability, owner.address, this.fiveSecondsSince)

await this.assetSAVAX.setPool(owner.address)
await this.assetSAVAX.addCash(sAvaxCash.sub(sAvaxLiability))
await this.sAVAX.transfer(this.assetSAVAX.address, sAvaxCash.sub(sAvaxLiability))
await this.assetSAVAX.setPool(this.pool.address)

await expectAssetValues(this.assetSAVAX, 18, { cash: '1478053.383', liability: '747812.6418' })

// AVAX SETUP
const avaxCash = parseEther('801521.1967')
const avaxLiability = parseEther('1592988.997')

await this.pool.deposit(this.WETH.address, avaxLiability, owner.address, this.fiveSecondsSince)
await this.assetAVAX.setPool(owner.address)
await this.assetAVAX.removeCash(avaxLiability.sub(avaxCash))
await this.assetAVAX.transferUnderlyingToken(owner.address, avaxLiability.sub(avaxCash))
// await this.WETH.transfer(this.assetAVAX.address, avaxCash.sub(avaxLiability))
await this.assetAVAX.setPool(this.pool.address)

await expectAssetValues(this.assetAVAX, 18, { cash: '801521.1967', liability: '1592988.997' })
})

describe('Withdraw Fee test', function () {
it('Withdraw test', async function () {
// this.WETH balance before and after
const avaxBalanceBefore = await this.WETH.balanceOf(owner.address)

await this.pool.withdraw(this.WETH.address, parseEther('1020000'), 0, owner.address, this.fiveSecondsSince)
const avaxBalanceAfter = await this.WETH.balanceOf(owner.address)

const delta = avaxBalanceAfter.sub(avaxBalanceBefore)
// console.log('delta', ethers.utils.formatEther(delta))
expect(delta).to.be.eq(ethers.utils.parseEther('589427.781262942888425645'))
})
})
})
})

0 comments on commit e8f931a

Please sign in to comment.