123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- const { expect } = require("chai")
- const { ethers } = require("hardhat")
- const { BigNumber } = require("ethers")
- const { setup } = require("./util/setup")
- const {
- encodePackedParams,
- getAddr,
- deployNew,
- callAsContract,
- encodeParams,
- amountSDtoLD,
- amountLDtoSD,
- getPoolFromFactory,
- } = require("./util/helpers")
- const {
- ZERO_ADDRESS,
- USDC,
- DAI,
- ETHEREUM,
- AVAX,
- TYPE_REDEEM_LOCAL_RESPONSE,
- TYPE_REDEEM_LOCAL_CALLBACK_RETRY,
- TYPE_SWAP_REMOTE_RETRY,
- } = require("./util/constants")
- const { addLiquidity, equalize, mintAndSwap, removeLiquidityLocal, removeLiquidityRemote, removeLiquidityInstant } = require("./util/actions")
- const { audit, getPoolState } = require("./util/poolStateHelpers")
- describe("Pool State: ", function () {
- this.timeout(600000000)
- let eth_endpoint, avax_endpoint, endpoints, tokens, pools
- let eth_usdc_pool, eth_dai_pool, avax_usdc_pool, avax_dai_pool
- let alice, bob, badUser1, fakeContract, emptyLzTxObj, defaultSwapObj
- before(async function () {
- ;({ alice, bob, badUser1, fakeContract } = await getAddr(ethers))
- })
- beforeEach(async function () {
- endpoints = await setup(2, 2)
- eth_endpoint = endpoints[ETHEREUM]
- avax_endpoint = endpoints[AVAX]
- ;({ [DAI]: eth_dai_pool, [USDC]: eth_usdc_pool } = eth_endpoint.pools)
- ;({ [DAI]: avax_dai_pool, [USDC]: avax_usdc_pool } = avax_endpoint.pools)
- endpoints = [eth_endpoint, avax_endpoint]
- pools = [eth_dai_pool, avax_dai_pool, eth_usdc_pool, avax_usdc_pool]
- tokens = [DAI]
- emptyLzTxObj = { dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x" }
- defaultSwapObj = { amount: 1, eqFee: 1, eqReward: 1, lpFee: 1, protocolFee: 1, lkbRemove: 1 }
- })
- it("swap() - lzTxParams transfers extra gas", async function () {
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("1000"))
- await equalize(endpoints, alice, false)
- const nativeAmt = 453
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: nativeAmt, dstNativeAddr: encodedDstNativeAddr }
- // mock is design to throw if this does not pass
- await expect(mintAndSwap(eth_dai_pool, avax_dai_pool, bob, BigNumber.from("500"), lzTxParams)).to.be.revertedWith(
- "NativeGasParams check"
- )
- })
- it("swap() - reverts with 0 amount", async function () {
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x" }
- await expect(
- eth_dai_pool.router
- .connect(alice)
- .swap(avax_dai_pool.chainId, eth_dai_pool.id, avax_dai_pool.id, alice.address, 0, 0, lzTxParams, alice.address, "0x")
- ).to.revertedWith("Stargate: cannot swap 0")
- })
- it("swap() - reverts when cp balance is not high enough for swap", async function () {
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("10000000"), {})
- await addLiquidity(eth_dai_pool, alice, BigNumber.from("10000000"), {})
- await equalize(endpoints, bob, false)
- // amount sd and ld are the same for this state
- const amountSD = BigNumber.from("2500000")
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x" }
- // mint and swap enough that it makes eqReward larger than the lp fee
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, amountSD, lzTxParams)
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, amountSD, lzTxParams)
- // when we try to swap the other way the total amount of the chain path, it tries to deduct more than the amountSD
- await expect(mintAndSwap(eth_dai_pool, avax_dai_pool, bob, amountSD.mul(3), lzTxParams)).to.revertedWith("Stargate: dst balance too low")
- })
- it("swap() - reverts when cp balance is not high enough for swap", async function () {
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("10000000"), {})
- await addLiquidity(eth_dai_pool, alice, BigNumber.from("10000000"), {})
- await equalize(endpoints, bob, false)
- // amount sd and ld are the same for this state
- const amountSD = BigNumber.from("2500000")
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x" }
- // mint and swap enough that it makes eqReward larger than the lp fee
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, amountSD, lzTxParams)
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, amountSD, lzTxParams)
- // when we try to swap the other way the total amount of the chain path, it tries to deduct more than the amountSD
- await expect(mintAndSwap(eth_dai_pool, avax_dai_pool, bob, amountSD.mul(3), lzTxParams)).to.revertedWith("Stargate: dst balance too low")
- })
- it("swap() - using loop back mock, revert on sgReceive when paused", async function () {
- const minAmountLD = BigNumber.from("1")
- const amountLD = BigNumber.from("66")
- const loopBackMock = await deployNew("LoopBackMock", [avax_dai_pool.router.address])
- const encodedDstNativeAddr = encodePackedParams(["address"], [loopBackMock.address])
- const lzTxParams = { dstGasForCall: 500000, dstNativeAmount: 123400, dstNativeAddr: encodedDstNativeAddr }
- const payload = encodeParams(["uint256", "uint256"], [avax_dai_pool.id, eth_dai_pool.id])
- // give the loop back some ether to transfer via lzTxParams
- await alice.sendTransaction({
- to: loopBackMock.address,
- value: 1000000,
- })
- // ensure liquidity in pools for swap
- await addLiquidity(eth_dai_pool, alice, BigNumber.from("1000000"))
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("1000000"))
- // update the chain path balances
- await equalize(endpoints, bob, false)
- // check the loop back has no tokens yet
- expect(await avax_dai_pool.token.balanceOf(loopBackMock.address)).to.equal(0)
- // give alice tokens to spend
- await eth_dai_pool.token.mint(alice.address, amountLD)
- // allow the eth router to spend them
- await eth_dai_pool.token.connect(alice).increaseAllowance(eth_dai_pool.router.address, amountLD)
- expect(await eth_dai_pool.token.balanceOf(alice.address)).to.equal(amountLD)
- // allow the loopback mock to send back half of the original amount back
- await callAsContract(avax_dai_pool.token, loopBackMock.address, "increaseAllowance(address,uint256)", [
- avax_dai_pool.router.address,
- amountLD.div(2),
- ])
- // pause the loop back contract
- await loopBackMock.pause(true)
- // increase the nonce by 1 because it is the next one
- const nonce = (await eth_endpoint.lzEndpoint.inboundNonce(avax_endpoint.chainId, eth_dai_pool.bridge.address)).add(1)
- await expect(
- eth_dai_pool.router
- .connect(alice)
- .swap(
- avax_dai_pool.chainId,
- eth_dai_pool.id,
- avax_dai_pool.id,
- alice.address,
- amountLD,
- minAmountLD,
- lzTxParams,
- loopBackMock.address,
- payload
- )
- ).to.emit(avax_dai_pool.router, "CachedSwapSaved")
- // can not clear the swap because it is paused
- await expect(avax_dai_pool.router.clearCachedSwap(eth_dai_pool.chainId, eth_dai_pool.bridge.address, nonce)).to.revertedWith(
- "Failed sgReceive due to pause"
- )
- // unpause
- await loopBackMock.pause(false)
- // unpaused, should clear
- await avax_dai_pool.router.clearCachedSwap(eth_dai_pool.chainId, eth_dai_pool.bridge.address, nonce)
- expect(await avax_dai_pool.token.balanceOf(loopBackMock.address)).to.equal(amountLD.div(2))
- // _srcAddress is where the tokens pass back to after LoopBackMock.sol
- expect(await eth_dai_pool.token.balanceOf(eth_dai_pool.bridge.address)).to.equal(amountLD.div(2))
- })
- it("swap() - using loop back mock, can send on sgReceive", async function () {
- const minAmountLD = BigNumber.from("1")
- const amountLD = BigNumber.from("66")
- const loopBackMock = await deployNew("LoopBackMock", [avax_dai_pool.router.address])
- const encodedDstNativeAddr = encodePackedParams(["address"], [loopBackMock.address])
- const lzTxParams = { dstGasForCall: 500000, dstNativeAmount: 123400, dstNativeAddr: encodedDstNativeAddr }
- const payload = encodeParams(["uint256", "uint256"], [avax_dai_pool.id, eth_dai_pool.id])
- // give the loop back some ether to transfer via lzTxParams
- await alice.sendTransaction({
- to: loopBackMock.address,
- value: 1000000,
- })
- // ensure liquidity in pools for swap
- await addLiquidity(eth_dai_pool, alice, BigNumber.from("1000000"))
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("1000000"))
- // update the chain path balances
- await equalize(endpoints, bob, false)
- // check the loop back has no tokens yet
- expect(await avax_dai_pool.token.balanceOf(loopBackMock.address)).to.equal(0)
- // give alice tokens to spend
- await eth_dai_pool.token.mint(alice.address, amountLD)
- // allow the eth router to spend them
- await eth_dai_pool.token.connect(alice).increaseAllowance(eth_dai_pool.router.address, amountLD)
- expect(await eth_dai_pool.token.balanceOf(alice.address)).to.equal(amountLD)
- // allow the loopback mock to send back half of the original amount back
- await callAsContract(avax_dai_pool.token, loopBackMock.address, "increaseAllowance(address,uint256)", [
- avax_dai_pool.router.address,
- amountLD.div(2),
- ])
- // initial swap tx can call send again and loop back in the same tx
- await expect(
- eth_dai_pool.router
- .connect(alice)
- .swap(
- avax_dai_pool.chainId,
- eth_dai_pool.id,
- avax_dai_pool.id,
- alice.address,
- amountLD,
- minAmountLD,
- lzTxParams,
- loopBackMock.address,
- payload
- )
- )
- .to.emit(loopBackMock, "LoopBack")
- .withArgs(eth_dai_pool.bridge.address.toLowerCase(), avax_dai_pool.id, eth_dai_pool.id, amountLD.div(2))
- expect(await avax_dai_pool.token.balanceOf(loopBackMock.address)).to.equal(amountLD.div(2))
- // _srcAddress is where the tokens pass back to after LoopBackMock.sol
- expect(await eth_dai_pool.token.balanceOf(eth_dai_pool.bridge.address)).to.equal(amountLD.div(2))
- })
- describe("LP pools are filled and fees set:", async function () {
- const amount = BigNumber.from("100000")
- beforeEach(async function () {
- // setting these fees allow delta credit to accumulate
- avax_endpoint.router.setFees(avax_dai_pool.id, 2)
- eth_endpoint.router.setFees(eth_dai_pool.id, 2)
- avax_endpoint.router.setDeltaParam(
- avax_dai_pool.id,
- true,
- 500, // 5%
- 500, // 5%
- true, //default
- true //default
- )
- eth_endpoint.router.setDeltaParam(
- eth_dai_pool.id,
- true,
- 500, // 5%
- 500, // 5%
- true, //default
- true //default
- )
- await addLiquidity(avax_dai_pool, alice, amount)
- await addLiquidity(eth_dai_pool, alice, amount)
- await addLiquidity(avax_dai_pool, bob, amount)
- await addLiquidity(avax_dai_pool, bob, amount)
- await equalize(endpoints, bob, false)
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, BigNumber.from(123), {}, false)
- })
- it("delta() - run a series of tests NOT in fullMode and ensure audit still works", async function () {
- const bigAmount = BigNumber.from("100000000000000")
- // turn full mode off
- avax_endpoint.router.setDeltaParam(
- avax_dai_pool.id,
- true,
- 500, // 5%
- 500, // 5%
- false, // non-default
- false // non-default
- )
- eth_endpoint.router.setDeltaParam(
- eth_dai_pool.id,
- true,
- 500, // 5%
- 500, // 5%
- false, // non-default
- false // non-default
- )
- // arbitrary set of actions
- await addLiquidity(avax_dai_pool, alice, bigAmount)
- await addLiquidity(eth_dai_pool, alice, bigAmount)
- await addLiquidity(avax_dai_pool, bob, bigAmount)
- await addLiquidity(eth_dai_pool, bob, bigAmount)
- await addLiquidity(avax_usdc_pool, bob, bigAmount)
- await addLiquidity(eth_usdc_pool, bob, bigAmount)
- await equalize(endpoints, bob, false)
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, BigNumber.from(10000000000000), {})
- await removeLiquidityRemote(eth_dai_pool, avax_dai_pool, alice, BigNumber.from(100000000000))
- await mintAndSwap(eth_dai_pool, avax_dai_pool, alice, BigNumber.from(10000000000000), {})
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, BigNumber.from(10000000000000), {})
- await mintAndSwap(avax_dai_pool, eth_usdc_pool, bob, BigNumber.from(10000000000000), {})
- await removeLiquidityRemote(eth_dai_pool, avax_usdc_pool, alice, BigNumber.from(100000000000))
- await audit(endpoints, pools)
- })
- it("redeemRemote() - add eqReward to the deltaCredits", async function () {
- const bigAmount = BigNumber.from("100000000000000")
- await addLiquidity(avax_dai_pool, alice, bigAmount)
- await addLiquidity(eth_dai_pool, alice, bigAmount)
- await equalize(endpoints, bob, false)
- // create an eq fee reward deficit so reward is generated on remove liquidity remote
- await mintAndSwap(avax_dai_pool, eth_dai_pool, bob, BigNumber.from(10000000000000), {}, true)
- const deltaCredit = await eth_dai_pool.pool.deltaCredit()
- await removeLiquidityRemote(eth_dai_pool, avax_dai_pool, alice, BigNumber.from(100000000000))
- // delta credits increases because the eq reward is added to it
- expect((await eth_dai_pool.pool.deltaCredit()).gt(deltaCredit)).to.equal(true)
- })
- it("redeemRemote() - nativeGasParams blocks", async function () {
- const nativeAmt = 453
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: nativeAmt, dstNativeAddr: encodedDstNativeAddr }
- const dstChainId = eth_endpoint.chainId
- // remove gas object so it gets stored properly, Passing ZERO_ADDRESS causes it to revert
- await expect(
- avax_endpoint.router.connect(bob).redeemRemote(dstChainId, DAI, DAI, bob.address, 1000, 1, ZERO_ADDRESS, lzTxParams)
- ).to.be.revertedWith("NativeGasParams check")
- })
- it("redeemRemote() - calls delta when lpDeltaBP is 0", async function () {
- avax_endpoint.router.setDeltaParam(
- avax_dai_pool.id,
- true,
- 0, // 0%
- 0, // 0%
- true, //default
- true //default
- )
- const deltaCredit = await avax_dai_pool.pool.deltaCredit()
- await removeLiquidityRemote(avax_dai_pool, eth_dai_pool, bob, BigNumber.from(1))
- expect((await avax_dai_pool.pool.deltaCredit()).lt(deltaCredit)).to.equal(true)
- })
- it("redeemRemote() - reverts when not enough lp", async function () {
- await expect(
- callAsContract(avax_dai_pool.pool, avax_endpoint.router.address, "redeemRemote(uint16,uint256,address,uint256)", [
- eth_dai_pool.chainId,
- eth_dai_pool.id,
- fakeContract.address,
- amount.add(1),
- ])
- ).to.revertedWith("Stargate: not enough LP tokens to burn")
- })
- it("redeemRemote() - lzTxParams transfers extra gas", async function () {
- const nativeAmt = 453
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: nativeAmt, dstNativeAddr: encodedDstNativeAddr }
- await expect(removeLiquidityRemote(avax_dai_pool, eth_dai_pool, bob, BigNumber.from("50"), lzTxParams)).to.be.revertedWith(
- "NativeGasParams check"
- )
- })
- it("redeemLocal()", async function () {
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 1000000, dstNativeAmount: 0, dstNativeAddr: encodedDstNativeAddr }
- await removeLiquidityLocal(avax_dai_pool, eth_dai_pool, alice, BigNumber.from("200"), lzTxParams, [], [], false)
- })
- it("redeemLocal() - lzTxParams transfers extra gas", async function () {
- const nativeAmt = 453
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: nativeAmt, dstNativeAddr: encodedDstNativeAddr }
- const srcChainId = avax_endpoint.chainId
- const dstChainId = eth_endpoint.chainId
- await expect(
- avax_endpoint.router.connect(bob).redeemLocal(dstChainId, DAI, DAI, bob.address, 1000, bob.address, lzTxParams)
- ).to.be.revertedWith("NativeGasParams check")
- // nonce is actually the next one, hence +1
- const expectedNonce = (await avax_dai_pool.lzEndpoint.outboundNonce(dstChainId, avax_dai_pool.bridge.address)).add(1)
- // remove gas object so it gets stored properly, then try to send it back the other way and hopefully get a revert
- await expect(avax_endpoint.router.connect(bob).redeemLocal(dstChainId, DAI, DAI, bob.address, 1000, bob.address, emptyLzTxObj))
- .to.emit(eth_endpoint.router, "RevertRedeemLocal")
- .withArgs(srcChainId, DAI, DAI, bob.address.toLowerCase(), 1000, 0, expectedNonce, avax_dai_pool.bridge.address.toLowerCase())
- await expect(
- eth_endpoint.router
- .connect(bob)
- .revertRedeemLocal(srcChainId, avax_endpoint.bridge.address, expectedNonce, bob.address, lzTxParams)
- ).to.be.revertedWith("NativeGasParams check")
- })
- it("retryRevert() - reverts when you try to send an invalid function", async function () {
- const srcChainId = avax_endpoint.chainId
- const dstChainId = eth_endpoint.chainId
- // remove gas object so it gets stored properly, then try to send it back the other way and hopefully get a revert
- await expect(avax_endpoint.router.connect(bob).redeemLocal(dstChainId, DAI, DAI, bob.address, 1000, bob.address, emptyLzTxObj))
- // nonce is actually the next one, hence +1
- const expectedNonce = (await avax_dai_pool.lzEndpoint.outboundNonce(dstChainId, avax_dai_pool.bridge.address)).add(1)
- await expect(
- eth_endpoint.router.connect(bob).retryRevert(srcChainId, avax_endpoint.bridge.address, expectedNonce)
- ).to.be.revertedWith("Stargate: invalid function type")
- })
- it("addLiquidity() - reverts when the safeTransferFrom fails", async function () {
- // pause transfers
- await avax_dai_pool.token.pauseTransfers(true)
- await expect(avax_dai_pool.router.addLiquidity(avax_dai_pool.id, 1, bob.address)).to.revertedWith("Stargate: TRANSFER_FROM_FAILED")
- })
- it("redeemLocalCheckOnRemote() - stores a payload on failed msg, then clears upon pool creation", async function () {
- const nonce = 1
- const srcChainId = 5
- const srcPoolId = 55
- const amountSD = BigNumber.from(69) // always keep it
- // simulate a situation where the user has already burned these lp tokens on the source side, and we are trying to complete the cycle on the other
- await expect(
- callAsContract(
- avax_dai_pool.router,
- avax_endpoint.bridge.address,
- "redeemLocalCheckOnRemote(uint16,bytes,uint256,uint256,uint256,uint256,bytes)",
- [srcChainId, eth_dai_pool.bridge.address, nonce, srcPoolId, avax_dai_pool.id, amountSD, bob.address]
- )
- )
- .to.emit(avax_dai_pool.router, "Revert")
- .withArgs(TYPE_REDEEM_LOCAL_RESPONSE, srcChainId, eth_dai_pool.bridge.address.toLowerCase(), nonce)
- // create and setup a pool for this to be sent to now
- await avax_endpoint.router.createChainPath(avax_dai_pool.id, srcChainId, srcPoolId, 1)
- await avax_endpoint.router.activateChainPath(avax_dai_pool.id, srcChainId, srcPoolId)
- await avax_endpoint.bridge.setBridge(srcChainId, eth_endpoint.bridge.address)
- await eth_endpoint.router.createPool(srcPoolId, eth_dai_pool.token.address, 18, 18, "x", "xx")
- await eth_endpoint.router.createChainPath(srcPoolId, avax_dai_pool.chainId, avax_dai_pool.id, 1)
- await eth_endpoint.router.activateChainPath(srcPoolId, avax_dai_pool.chainId, avax_dai_pool.id)
- const srcPool = await getPoolFromFactory(eth_endpoint.factory, srcPoolId)
- await expect(avax_dai_pool.router.retryRevert(srcChainId, eth_endpoint.bridge.address, nonce)).to.revertedWith(
- "Stargate: invalid function type"
- )
- // is a stored revert
- expect(await avax_dai_pool.router.revertLookup(srcChainId, eth_endpoint.bridge.address, nonce)).to.not.equal("0x")
- const userBalance = await srcPool.balanceOf(bob.address)
- // revert - the swap amount has been set to 0, because the deduction of chain path balances on the remote side failed
- // the full amount of lp that was attempted to burn, is minted back to the user, as if nothing happened
- await expect(
- avax_dai_pool.router.revertRedeemLocal(srcChainId, eth_endpoint.bridge.address, nonce, fakeContract.address, emptyLzTxObj)
- )
- .to.emit(srcPool, "RedeemLocalCallback")
- .withArgs(bob.address, 0, amountSD)
- // user gets minted back the full amount upon completion
- expect(await srcPool.balanceOf(bob.address)).to.equal(userBalance.add(amountSD))
- // make sure the payload is cleared
- expect(await avax_dai_pool.router.revertLookup(srcChainId, eth_endpoint.bridge.address, nonce)).to.equal("0x")
- // can not send another one
- await expect(avax_dai_pool.router.retryRevert(srcChainId, eth_endpoint.bridge.address, nonce)).to.revertedWith(
- "Stargate: no retry revert"
- )
- })
- it("redeemLocalCallback() - stores a payload on failed msg", async function () {
- const nonce = 1
- // pause transfers
- await avax_dai_pool.token.pauseTransfers(true)
- await expect(
- callAsContract(
- avax_dai_pool.router,
- avax_endpoint.bridge.address,
- "redeemLocalCallback(uint16,bytes,uint256,uint256,uint256,address,uint256,uint256)",
- [eth_dai_pool.chainId, eth_dai_pool.bridge.address, nonce, eth_dai_pool.id, avax_dai_pool.id, bob.address, 1, 1]
- )
- )
- .to.emit(avax_dai_pool.router, "Revert")
- .withArgs(TYPE_REDEEM_LOCAL_CALLBACK_RETRY, eth_dai_pool.chainId, eth_dai_pool.bridge.address.toLowerCase(), nonce)
- await expect(
- avax_dai_pool.router.revertRedeemLocal(
- eth_dai_pool.chainId,
- eth_endpoint.bridge.address,
- nonce,
- fakeContract.address,
- emptyLzTxObj
- )
- ).to.revertedWith("Stargate: invalid function type")
- // unpause transfers and revert
- await avax_dai_pool.token.pauseTransfers(false)
- await avax_dai_pool.router.retryRevert(eth_dai_pool.chainId, eth_endpoint.bridge.address, nonce)
- // make sure the payload is cleared
- expect(await avax_dai_pool.router.revertLookup(eth_dai_pool.chainId, eth_endpoint.bridge.address, nonce)).to.equal("0x")
- // can not send another one
- await expect(avax_dai_pool.router.retryRevert(eth_dai_pool.chainId, eth_endpoint.bridge.address, nonce)).to.revertedWith(
- "Stargate: no retry revert"
- )
- })
- it("swapRemote() - stores a payload on failed msg", async function () {
- const nonce = 1
- // pause transfers
- await avax_dai_pool.token.pauseTransfers(true)
- await expect(
- callAsContract(
- avax_dai_pool.router,
- avax_endpoint.bridge.address,
- "swapRemote(uint16,bytes,uint256,uint256,uint256,uint256,address,(uint256,uint256,uint256,uint256,uint256,uint256),bytes)",
- [
- avax_dai_pool.chainId,
- avax_dai_pool.bridge.address,
- nonce,
- avax_dai_pool.id,
- eth_dai_pool.id,
- 0,
- bob.address,
- defaultSwapObj,
- "0x",
- ]
- )
- )
- .to.emit(avax_dai_pool.router, "Revert")
- .withArgs(TYPE_SWAP_REMOTE_RETRY, avax_dai_pool.chainId, avax_dai_pool.bridge.address.toLowerCase(), nonce)
- await expect(
- avax_dai_pool.router.revertRedeemLocal(
- avax_dai_pool.chainId,
- avax_endpoint.bridge.address,
- nonce,
- fakeContract.address,
- emptyLzTxObj
- )
- ).to.revertedWith("Stargate: invalid function type")
- // unpause transfers and revert
- await avax_dai_pool.token.pauseTransfers(false)
- await avax_dai_pool.router.retryRevert(avax_dai_pool.chainId, avax_endpoint.bridge.address, nonce)
- // make sure the payload is cleared
- expect(await avax_dai_pool.router.revertLookup(avax_dai_pool.chainId, avax_endpoint.bridge.address, nonce)).to.equal("0x")
- // can not send another one
- await expect(avax_dai_pool.router.retryRevert(avax_dai_pool.chainId, avax_endpoint.bridge.address, nonce)).to.revertedWith(
- "Stargate: no retry revert"
- )
- })
- it("instantRedeemLocal() - redeems less than the cap", async function () {
- const deltaCredit = await avax_dai_pool.pool.deltaCredit()
- const userBal = await avax_dai_pool.token.balanceOf(bob.address)
- await removeLiquidityInstant(avax_dai_pool, bob, deltaCredit.sub(1))
- expect(await avax_dai_pool.token.balanceOf(bob.address)).to.equal(userBal.add(deltaCredit.sub(1)))
- })
- it("instantRedeemLocal() - only burns/redeems the cap", async function () {
- const deltaCredit = await avax_dai_pool.pool.deltaCredit()
- const userBal = await avax_dai_pool.token.balanceOf(bob.address)
- // try to redeem 1 more than delta credits, should only get the max amount od delta credits back
- await removeLiquidityInstant(avax_dai_pool, bob, deltaCredit.add(1))
- expect(await avax_dai_pool.token.balanceOf(bob.address)).to.equal(userBal.add(deltaCredit))
- })
- it("instantRedeemLocal() - reverts when from address is 0x0", async function () {
- await addLiquidity(avax_dai_pool, alice, BigNumber.from(100))
- await expect(
- callAsContract(avax_dai_pool.pool, avax_dai_pool.router.address, "instantRedeemLocal(address,uint256,address)", [
- ZERO_ADDRESS,
- 1,
- alice.address,
- ])
- ).to.revertedWith("Stargate: _from cannot be 0x0")
- })
- it("redeemLocalCallback() - mints to user", async function () {
- const amountSD = BigNumber.from(1000)
- const amountToMintSD = BigNumber.from(435)
- let amountLP = amountLDtoSD(amountSDtoLD(amountToMintSD, avax_dai_pool), avax_dai_pool)
- const { totalSupply, totalLiquidity } = await getPoolState(avax_dai_pool)
- if (totalSupply.gt(0)) amountLP = amountLP.mul(totalSupply).div(totalLiquidity)
- const userLpBalance = await avax_dai_pool.pool.balanceOf(bob.address)
- await expect(
- callAsContract(avax_dai_pool.pool, avax_endpoint.router.address, "redeemLocalCallback(uint16,uint256,address,uint256,uint256)", [
- eth_dai_pool.chainId,
- eth_dai_pool.id,
- bob.address,
- amountSD,
- amountToMintSD,
- ])
- )
- .to.emit(avax_dai_pool.pool, "RedeemLocalCallback")
- .withArgs(bob.address, amountSD, amountToMintSD)
- // make sure the user got the expected amount of lp
- expect(await avax_dai_pool.pool.balanceOf(bob.address)).to.equal(userLpBalance.add(amountLP))
- })
- it("redeemLocal() - reverts when amountSD is 0", async function () {
- const storageLocationTotalLiquidity = "0xe" // position in contract storage
- const setTotalLiquidityValue = "0x0000000000000000000000000000000000000000000000000000000000000001" // totalLiquidity = 1
- // set totalLiquidity to 1
- await network.provider.send("hardhat_setStorageAt", [
- avax_dai_pool.pool.address,
- storageLocationTotalLiquidity,
- setTotalLiquidityValue,
- ])
- await expect(callRedeemLocal(avax_dai_pool, eth_dai_pool, bob, 1000, emptyLzTxObj)).to.revertedWith(
- "Stargate: not enough lp to redeem with amountSD"
- )
- })
- })
- it("redeemLocal() - reverts when lp isnt enough", async function () {
- const nativeAmt = 100
- const encodedDstNativeAddr = encodePackedParams(["address"], [alice.address])
- const lzTxParams = { dstGasForCall: 0, dstNativeAmount: nativeAmt, dstNativeAddr: encodedDstNativeAddr }
- await addLiquidity(avax_dai_pool, alice, BigNumber.from("1"))
- await expect(removeLiquidityLocal(avax_dai_pool, eth_dai_pool, alice, BigNumber.from("0"), lzTxParams)).to.be.revertedWith(
- "Stargate: not enough lp to redeem"
- )
- })
- it("instantRedeemLocal() - reverts when totalLiquidity is 0", async function () {
- await expect(avax_dai_pool.router.connect(alice).instantRedeemLocal(avax_dai_pool.id, 1, ZERO_ADDRESS)).to.revertedWith(
- "Stargate: cant convert SDtoLP when totalLiq == 0'"
- )
- })
- })
|