123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- const { expect } = require("chai")
- const { ethers } = require("hardhat")
- const { TYPE_SWAP_REMOTE, TYPE_ADD_LIQUIDITY, TYPE_REDEEM_LOCAL_CALL_BACK, TYPE_WITHDRAW_REMOTE, ZERO_ADDRESS } = require("./util/constants")
- const { callAsContract, getAddr, deployNew, encodeParams } = require("./util/helpers")
- describe("Bridge:", function () {
- let owner, alice, badUser1, fakeContract, router, mockToken, lzEndpoint, bridge
- let chainId, nonce, defaultGasAmount, transferAndCallPayload, defaultCreditObj, defaulSwapObject, defaultLzTxObj
- before(async function () {
- ;({ owner, alice, badUser1, fakeContract } = await getAddr(ethers))
- chainId = 1
- nonce = 1
- defaultGasAmount = 123
- transferAndCallPayload = "0x"
- defaultCreditObj = { credits: 0, idealBalance: 0 }
- defaulSwapObject = { amount: 0, eqFee: 0, eqReward: 0, lpFee: 0, protocolFee: 0, lkbRemove: 0 }
- defaultLzTxObj = { dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x" }
- })
- beforeEach(async function () {
- router = await deployNew("Router")
- mockToken = await deployNew("MockToken", ["Token", "TKN", 18])
- lzEndpoint = await deployNew("LZEndpointMock", [chainId])
- bridge = await deployNew("Bridge", [lzEndpoint.address, router.address])
- })
- it("constructor() - reverts for 0x0 LZ endpoint", async function () {
- await expect(deployNew("Bridge", [ZERO_ADDRESS, ZERO_ADDRESS])).to.be.revertedWith("Stargate: _layerZeroEndpoint cannot be 0x0")
- })
- it("constructor() - reverts for 0x0 router endpoint", async function () {
- await expect(deployNew("Bridge", [fakeContract.address, ZERO_ADDRESS])).to.be.revertedWith("Stargate: _router cannot be 0x0")
- })
- it("renounceOwnership() - does not affect ownership", async function () {
- expect(await bridge.owner()).to.equal(owner.address)
- await bridge.renounceOwnership()
- expect(await bridge.owner()).to.equal(owner.address)
- })
- it("swap() - reverts when non owner", async function () {
- await expect(bridge.swap(1, 1, 1, ZERO_ADDRESS, defaultCreditObj, defaulSwapObject, defaultLzTxObj, "0x", "0x")).to.revertedWith(
- "Stargate: caller must be Router."
- )
- })
- it("redeemLocalCallback() - reverts when non owner", async function () {
- await expect(bridge.redeemLocalCallback(1, ZERO_ADDRESS, defaultCreditObj, defaultLzTxObj, "0x")).to.revertedWith(
- "Stargate: caller must be Router."
- )
- })
- it("lzReceive() - reverts for non LZ endpoint", async function () {
- await expect(bridge.lzReceive(chainId, alice.address, nonce, alice.address)).to.be.revertedWith(
- "Stargate: only LayerZero endpoint can call lzReceive"
- )
- })
- it("lzReceive() - does NOT revert if invalid function type passed", async function () {
- const payload = encodeParams(["uint256", "uint8"], [123, 123])
- await expect(
- callAsContract(bridge, lzEndpoint.address, "lzReceive(uint16,bytes,uint64,bytes)", [chainId, "0x", nonce, payload])
- ).to.not.be.revertedWith()
- })
- it("lzReceive() - reverts for mismatched bridgeLookup", async function () {
- await bridge.setBridge(chainId, fakeContract.address)
- await expect(
- callAsContract(bridge, lzEndpoint.address, "lzReceive(uint16,bytes,uint64,bytes)", [chainId, alice.address, nonce, alice.address])
- ).to.be.revertedWith("Stargate: bridge does not match")
- })
- it("setBridge()", async function () {
- expect(await bridge.bridgeLookup(chainId)).to.equal("0x")
- await bridge.setBridge(chainId, fakeContract.address)
- expect(await bridge.bridgeLookup(chainId)).to.equal(fakeContract.address.toLowerCase()) // lowerCase because it returns bytes
- })
- it("setBridge() - reverts when bridge already set ", async function () {
- await bridge.setBridge(chainId, fakeContract.address) // set it first
- await expect(bridge.setBridge(chainId, fakeContract.address)).to.be.revertedWith("Stargate: Bridge already set!")
- })
- it("setBridge() - reverts for non owner", async function () {
- await expect(bridge.connect(badUser1).setBridge(chainId, fakeContract.address)).to.be.revertedWith("Ownable: caller is not the owner")
- })
- it("setGasAmount() - reverts for non owner", async function () {
- await expect(bridge.connect(badUser1).setGasAmount(chainId, TYPE_SWAP_REMOTE, defaultGasAmount)).to.be.revertedWith(
- "Ownable: caller is not the owner"
- )
- })
- it("setGasAmount() - reverts for invalid function type", async function () {
- const invalidFunctionType = 0
- await expect(bridge.setGasAmount(chainId, invalidFunctionType, defaultGasAmount)).to.be.revertedWith("Stargate: invalid _functionType")
- })
- it("setGasAmount()", async function () {
- await expect(bridge.setGasAmount(chainId, TYPE_SWAP_REMOTE, defaultGasAmount)).to.not.be.revertedWith("Stargate: invalid _functionType")
- expect(await bridge.gasLookup(chainId, TYPE_SWAP_REMOTE)).to.equal(defaultGasAmount)
- })
- it("approveTokenSpender() - reverts for non owner", async function () {
- await expect(bridge.connect(badUser1).approveTokenSpender(alice.address, badUser1.address, 0)).to.be.revertedWith(
- "Ownable: caller is not the owner"
- )
- })
- it("approveTokenSpender() - approves amount", async function () {
- expect(await mockToken.allowance(bridge.address, alice.address)).to.equal(0)
- const approveAmount = 1
- await bridge.approveTokenSpender(mockToken.address, alice.address, approveAmount)
- expect(await mockToken.allowance(bridge.address, alice.address)).to.equal(approveAmount)
- })
- it("setUseLayerZeroToken() - reverts for non owner", async function () {
- await expect(bridge.connect(badUser1).setUseLayerZeroToken(true)).to.be.revertedWith("Ownable: caller is not the owner")
- })
- it("setUseLayerZeroToken()", async function () {
- expect(await bridge.useLayerZeroToken()).to.equal(false)
- await bridge.setUseLayerZeroToken(true)
- expect(await bridge.useLayerZeroToken()).to.equal(true)
- })
- it("quoteLayerZeroFee() - TYPE_SWAP_REMOTE returns valid fee", async function () {
- expect(
- await bridge.quoteLayerZeroFee(chainId, TYPE_SWAP_REMOTE, fakeContract.address, transferAndCallPayload, {
- dstGasForCall: 0,
- dstNativeAmount: 0,
- dstNativeAddr: "0x",
- })
- ).to.deep.equal(await lzEndpoint.estimateFees(chainId, fakeContract.address, transferAndCallPayload, true, "0x"))
- })
- it("quoteLayerZeroFee() - TYPE_ADD_LIQUIDITY returns valid fee", async function () {
- expect(
- await bridge.quoteLayerZeroFee(chainId, TYPE_ADD_LIQUIDITY, fakeContract.address, transferAndCallPayload, {
- dstGasForCall: 0,
- dstNativeAmount: 0,
- dstNativeAddr: "0x",
- })
- ).to.deep.equal(await lzEndpoint.estimateFees(chainId, fakeContract.address, transferAndCallPayload, true, "0x"))
- })
- it("quoteLayerZeroFee() - TYPE_REDEEM_LOCAL_CALL_BACK returns valid fee", async function () {
- expect(
- await bridge.quoteLayerZeroFee(chainId, TYPE_REDEEM_LOCAL_CALL_BACK, fakeContract.address, transferAndCallPayload, {
- dstGasForCall: 0,
- dstNativeAmount: 0,
- dstNativeAddr: "0x",
- })
- ).to.deep.equal(await lzEndpoint.estimateFees(chainId, fakeContract.address, "0x", true, "0x"))
- })
- it("quoteLayerZeroFee() - TYPE_WITHDRAW_REMOTE returns valid fee", async function () {
- expect(
- await bridge.quoteLayerZeroFee(chainId, TYPE_WITHDRAW_REMOTE, fakeContract.address, transferAndCallPayload, {
- dstGasForCall: 0,
- dstNativeAmount: 0,
- dstNativeAddr: "0x",
- })
- ).to.deep.equal(await lzEndpoint.estimateFees(chainId, fakeContract.address, transferAndCallPayload, true, "0x"))
- })
- it("quoteLayerZeroFee() - reverts with unsupported tx type is sent", async function () {
- await expect(
- bridge.quoteLayerZeroFee(chainId, TYPE_WITHDRAW_REMOTE + 1, fakeContract.address, transferAndCallPayload, {
- dstGasForCall: 0,
- dstNativeAmount: 0,
- dstNativeAddr: "0x",
- })
- ).to.revertedWith("Stargate: unsupported function type")
- })
- it("setSendVersion()", async function () {
- const version = 22
- await bridge.setSendVersion(version)
- expect(await lzEndpoint.mockSendVersion()).to.equal(version)
- })
- it("setReceiveVersion()", async function () {
- const version = 23
- await bridge.setReceiveVersion(version)
- expect(await lzEndpoint.mockReceiveVersion()).to.equal(version)
- })
- it("setSendVersion() - reverts when non owner", async function () {
- const version = 22
- await expect(bridge.connect(badUser1).setSendVersion(version)).to.revertedWith("Ownable: caller is not the owner")
- })
- it("setReceiveVersion() - reverts when non owner", async function () {
- const version = 23
- await expect(bridge.connect(badUser1).setReceiveVersion(version)).to.revertedWith("Ownable: caller is not the owner")
- })
- it("setConfig()", async function () {
- const version = 22
- const configType = 0
- const config = "0x1234"
- await expect(bridge.setConfig(version, chainId, configType, config))
- .to.emit(lzEndpoint, "SetConfig")
- .withArgs(version, chainId, configType, config)
- })
- it("setConfig() - reverts when non owner", async function () {
- const version = 22
- const configType = 0
- const config = "0x1234"
- await expect(bridge.connect(badUser1).setConfig(version, chainId, configType, config)).to.revertedWith(
- "Ownable: caller is not the owner"
- )
- })
- it("forceResumeReceive()", async function () {
- const bytesAddr = "0x1234"
- await expect(bridge.forceResumeReceive(chainId, bytesAddr)).to.emit(lzEndpoint, "ForceResumeReceive").withArgs(chainId, bytesAddr)
- })
- it("forceResumeReceive() - reverts when non owner", async function () {
- const bytesAddr = "0x1234"
- await expect(bridge.connect(badUser1).forceResumeReceive(chainId, bytesAddr)).to.revertedWith("Ownable: caller is not the owner")
- })
- })
|