text: const { expect } = require('chai');
  const { ethers } = require('hardhat');
  const { timeTravel } = require('./utils');
  
  const AdminStatus = {
    Unauthorized: 0,
    Admin: 1,
    SuperAdmin: 2
  };
  
  let api3TokenLockExternalFactory;
  const ONE_MINUTE_IN_SECONDS = 60;
  const LOCK_AMOUNT = 10;
  
  const Errors = {
    ClientBlacklisted: 'Client blacklisted',
    ClientNotBlacklisted: 'Client not blacklisted',
    FromClientBlacklisted: 'From Client blacklisted',
    LockPeriodNotExpired: 'Locking period not expired',
    ToClientBlacklisted: 'To Client blacklisted',
    Unauthorized: 'Unauthorized',
    ZeroAddress: 'Zero address',
    ZeroAmount: 'Zero amount'
  }
  
  const airnodeId = ethers.utils.hexlify(ethers.utils.randomBytes(32));
  const chainId = 3;
  
  describe('Api3TokenLockExternal', async () => {
  
    beforeEach(async () => {
      [
        deployer,
        metaAdmin,
        newMetaAdmin,
        admin,
        alice,
        bobClient,
        carolClient,
        unknown
      ] = await ethers.getSigners();
  
      api3TokenLockExternalFactory = await ethers.getContractFactory('Api3TokenLockExternal', deployer);
    });
  
    describe('constructor', async () => {
      context('successful deployment', async () => {
        it('initialises correctly', async () => {
          // when:
          const api3TokenLockExternal = await api3TokenLockExternalFactory.deploy(metaAdmin.address, ONE_MINUTE_IN_SECONDS, LOCK_AMOUNT);
          // then:
  
          expect(await api3TokenLockExternal.metaAdmin()).to.equal(metaAdmin.address);
          expect(await api3TokenLockExternal.minimumLockingTime()).to.equal(ONE_MINUTE_IN_SECONDS);
          expect(await api3TokenLockExternal.lockAmount()).to.equal(LOCK_AMOUNT);
        });
      });
  
      context('Meta Admin is zero address', async () => {
        it('reverts', async () => {
          await expect(api3TokenLockExternalFactory.deploy(ethers.constants.AddressZero, ONE_MINUTE_IN_SECONDS, LOCK_AMOUNT))
            .to.revertedWith(Errors.ZeroAddress);
        });
      });
  
      context('Lock Amount is zero', async () => {
        it('reverts', async () => {
          await expect(api3TokenLockExternalFactory.deploy(metaAdmin.address, ONE_MINUTE_IN_SECONDS, 0))
            .to.revertedWith(Errors.ZeroAmount);
        });
      });
    });
  
    describe('post deployment', async () => {
      let api3TokenLockExternal;
      let api3Token;
  
      beforeEach(async () => {
        // deploy Api3TokenLock
        api3TokenLockExternal = await api3TokenLockExternalFactory.deploy(metaAdmin.address, ONE_MINUTE_IN_SECONDS, LOCK_AMOUNT);
  
        const api3TokenFactory = await ethers.getContractFactory('Api3Token', deployer);
        // deploy Api3Token
        api3Token = await api3TokenFactory.deploy(deployer.address, alice.address);
      });
  
      describe('setMetaAdmin', async () => {
        context('caller is meta admin', async () => {
          context('address to be set', async () => {
            it('is set', async () => {
              // when:
              await api3TokenLockExternal.connect(metaAdmin).setMetaAdmin(newMetaAdmin.address);
  
              // then:
              expect(await api3TokenLockExternal.metaAdmin()).to.equal(newMetaAdmin.address);
            });
  
            it('emits event', async () => {
              await expect(api3TokenLockExternal.connect(metaAdmin).setMetaAdmin(newMetaAdmin.address))
                .to.emit(api3TokenLockExternal, 'SetMetaAdmin')
                .withArgs(newMetaAdmin.address);
            });
          });
  
          context('new meta admin is zero address', async () => {
            it('reverts', async () => {
              await expect(api3TokenLockExternal.connect(metaAdmin).setMetaAdmin(ethers.constants.AddressZero))
                .to.revertedWith(Errors.ZeroAddress);
            });
          });
        });
  
        context('caller is not meta admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setMetaAdmin(newMetaAdmin.address))
              .to.revertedWith(Errors.Unauthorized);
          });
        });
      });
  
      describe('setAdminStatus', async () => {
        context('caller is meta admin', async () => {
          it('is set', async () => {
            // when:
            await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
            // then:
            expect(await api3TokenLockExternal.adminStatuses(admin.address)).to.equal(AdminStatus.Admin);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin))
              .to.emit(api3TokenLockExternal, 'SetAdminStatus')
              .withArgs(admin.address, AdminStatus.Admin);
          });
        });
  
        context('caller is not meta admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setAdminStatus(admin.address, AdminStatus.Admin))
              .to.revertedWith(Errors.Unauthorized);
          });
        });
      });
  
      describe('setApi3Token', async () => {
        beforeEach(async () => {
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
        });
  
        context('caller is admin', async () => {
          it('is set', async () => {
            // when:
            await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
            // then:
            expect(await api3TokenLockExternal.api3Token()).to.equal(api3Token.address);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address))
              .to.emit(api3TokenLockExternal, 'SetApi3Token')
              .withArgs(api3Token.address);
          });
  
          context('Api3Token is zero address', async () => {
            it('reverts', async () => {
              await expect(api3TokenLockExternal.connect(admin).setApi3Token(ethers.constants.AddressZero))
                .to.revertedWith(Errors.ZeroAddress);
            });
          });
  
          context('Api3Token does not implement IApi3Token interface', async () => {
            it('reverts', async () => {
              await expect(api3TokenLockExternal.connect(admin).setApi3Token(unknown.address))
                .to.reverted;
            });
          });
        });
  
        context('caller is not admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setApi3Token(api3Token.address))
              .to.revertedWith(Errors.Unauthorized);
          });
        });
      });
  
      describe('setMinimumLockingTime', async () => {
        const NEW_MINIMUM_LOCKING_TIME = 2 * ONE_MINUTE_IN_SECONDS;
  
        context('caller is admin', async () => {
          it('is set', async () => {
            // when:
            await api3TokenLockExternal.setMinimumLockingTime(NEW_MINIMUM_LOCKING_TIME);
            // then:
            expect(await api3TokenLockExternal.minimumLockingTime()).to.equal(NEW_MINIMUM_LOCKING_TIME);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.setMinimumLockingTime(NEW_MINIMUM_LOCKING_TIME))
              .to.emit(api3TokenLockExternal, 'SetMinimumLockingTime')
              .withArgs(NEW_MINIMUM_LOCKING_TIME);
          });
        });
  
        context('caller is not admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setMinimumLockingTime(NEW_MINIMUM_LOCKING_TIME))
              .to.revertedWith('caller is not the owner');
          });
        });
      });
  
      describe('setLockAmount', async () => {
        const NEW_LOCK_AMOUNT = 2 * LOCK_AMOUNT;
  
        context('caller is admin', async () => {
          it('is set', async () => {
            // when:
            await api3TokenLockExternal.setLockAmount(NEW_LOCK_AMOUNT);
            // then:
            expect(await api3TokenLockExternal.lockAmount()).to.equal(NEW_LOCK_AMOUNT);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.setLockAmount(NEW_LOCK_AMOUNT))
              .to.emit(api3TokenLockExternal, 'SetLockAmount')
              .withArgs(NEW_LOCK_AMOUNT);
          });
  
          context('new lock amount is zero', async () => {
            it('reverts', async () => {
              await expect(api3TokenLockExternal.setLockAmount(0))
                .to.revertedWith(Errors.ZeroAmount);
            });
          });
        });
  
        context('caller is not admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setLockAmount(NEW_LOCK_AMOUNT))
              .to.revertedWith('caller is not the owner');
          });
        });
      });
  
      describe('setBlacklistStatus', async () => {
        context('caller is owner', async () => {
          it('is set', async () => {
            // when:
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
            // then:
            expect(await api3TokenLockExternal.clientAddressToBlacklistStatus(bobClient.address)).to.equal(true);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.setBlacklistStatus(bobClient.address, true))
              .to.emit(api3TokenLockExternal, 'SetBlacklistStatus')
              .withArgs(bobClient.address, true, deployer.address);
          });
        });
        context('caller is not admin', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(unknown).setBlacklistStatus(bobClient.address, true))
              .to.revertedWith('caller is not the owner');
          });
        });
      });
  
      describe('lock', async () => {
        beforeEach(async () => {
          // set admin
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
  
          // set api3 token
          await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
        });
  
        context('caller is first time locking', async () => {
          beforeEach(async () => {
            // given:
            await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
          });
  
          it('is set', async () => {
            const beforeBalance = await api3Token.balanceOf(alice.address);
            // when:
            await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
            // then:
            const now = (await ethers.provider.getBlock(await ethers.provider.getBlockNumber())).timestamp;
            const expectedUnlockTime = now + ONE_MINUTE_IN_SECONDS;
            const afterBalance = await api3Token.balanceOf(alice.address);
  
            expect(afterBalance).to.equal(beforeBalance.sub(LOCK_AMOUNT));
  
            expect(await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(expectedUnlockTime);
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(LOCK_AMOUNT);
            expect(await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address)).to.equal(1);
          });
  
          it('emits event', async () => {
            // then:
            await expect(api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address))
              .to.emit(api3TokenLockExternal, 'Lock')
              .withArgs(chainId, airnodeId, bobClient.address, alice.address, LOCK_AMOUNT)
              .to.emit(api3TokenLockExternal, 'Authorize')
              .withArgs(chainId, airnodeId, bobClient.address, ethers.constants.MaxUint256);
          });
        });
  
        context('caller has already locked', async () => {
          it('reverts', async () => {
            // given:
            await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
            await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
            // then:
            await expect(api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address))
              .to.revertedWith('Already locked');
          });
        });
  
        context('client address is blacklisted', async () => {
          it('reverts', async () => {
            // given:
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
            // then:
            await expect(api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address))
              .to.revertedWith(Errors.ClientBlacklisted);
          });
        });
      });
  
      describe('unlock', async () => {
        beforeEach(async () => {
          // set admin
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
  
          // set api3 token
          await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
  
          // approve Api3TokenLock:
          await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
          // Lock:
          await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
        });
  
        context('caller is unlocking successfully', async () => {
          beforeEach(async () => {
            timeTravel(ONE_MINUTE_IN_SECONDS + 1);
          });
  
          it('is set', async () => {
            const beforeBalance = await api3Token.balanceOf(alice.address);
            // when:
            await api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address);
            // then:
            const afterBalance = await api3Token.balanceOf(alice.address);
            expect(afterBalance).to.equal(beforeBalance.add(LOCK_AMOUNT));
            expect(await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            expect(await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address)).to.equal(0);
          });
  
          it('emits event', async () => {
            // then:
            await expect(api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address))
              .to.emit(api3TokenLockExternal, 'Unlock')
              .withArgs(chainId, airnodeId, bobClient.address, alice.address, LOCK_AMOUNT)
              .to.emit(api3TokenLockExternal, 'Authorize')
              .withArgs(chainId, airnodeId, bobClient.address, 0);
          });
        });
  
        context('caller period not expired', async () => {
          it('reverts', async () => {
            // then:
            await expect(api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address))
              .to.revertedWith(Errors.LockPeriodNotExpired);
          });
        });
  
        context('already unlocked', async () => {
          it('reverts', async () => {
            // given:
            timeTravel(ONE_MINUTE_IN_SECONDS + 1);
            await api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address);
            // then:
            await expect(api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address))
              .to.revertedWith('No amount locked');
          });
        });
  
        context('client address is blacklisted', async () => {
          it('reverts', async () => {
            // given:
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
            timeTravel(ONE_MINUTE_IN_SECONDS);
            // then:
            await expect(api3TokenLockExternal.connect(alice).unlock(chainId, airnodeId, bobClient.address))
              .to.revertedWith(Errors.ClientBlacklisted);
          });
        });
      });
  
      describe('withdraw', async () => {
        const NEW_LOCK_AMOUNT = LOCK_AMOUNT / 2;
        const expectedWithdrawnAmount = LOCK_AMOUNT - NEW_LOCK_AMOUNT;
  
        beforeEach(async () => {
          // set admin
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
  
          // set api3 token
          await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
  
          // approve Api3TokenLock:
          await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
          // Lock:
          await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
        });
  
        context('successful withdraws amount if it is set to a lower one', async () => {
          beforeEach(async () => {
            await api3TokenLockExternal.setLockAmount(NEW_LOCK_AMOUNT);
          });
  
          it('withdraws', async () => {
            const beforeBalance = await api3Token.balanceOf(alice.address);
            // when:
            await api3TokenLockExternal.connect(alice).withdraw(chainId, airnodeId, bobClient.address);
            // then:
            const afterBalance = await api3Token.balanceOf(alice.address);
            expect(afterBalance).to.equal(beforeBalance.add(expectedWithdrawnAmount));
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(NEW_LOCK_AMOUNT);
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.connect(alice).withdraw(chainId, airnodeId, bobClient.address))
              .to.emit(api3TokenLockExternal, 'Withdraw')
              .withArgs(chainId, airnodeId, bobClient.address, alice.address, expectedWithdrawnAmount);
          });
        });
  
        context('client address is blacklisted', async () => {
          beforeEach(async () => {
            await api3TokenLockExternal.setLockAmount(NEW_LOCK_AMOUNT);
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
          });
  
          it('reverts', async () => {
            // then:
            await expect(api3TokenLockExternal.connect(alice).withdraw(chainId, airnodeId, bobClient.address))
              .to.revertedWith(Errors.ClientBlacklisted);
          });
        });
  
        context('locked amount is not reduced', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.connect(alice).withdraw(chainId, airnodeId, bobClient.address))
              .to.revertedWith('Insufficient amount');
          });
        });
      });
  
      describe('transfer', async () => {
        beforeEach(async () => {
          // set admin
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
  
          // set api3 token
          await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
  
          // approve Api3TokenLock:
          await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
  
          // Lock:
          await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
        });
  
        context('from one client to another', async () => {
          it('is set', async () => {
            const lockPeriod = await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address);
            const lockAmount = await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address);
            const beforeBobWhitelistCount = await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address);
            const beforeCarolWhitelistCount = await api3TokenLockExternal.tokenLocks(chainId, airnodeId, carolClient.address);
  
            // when:
            await api3TokenLockExternal.connect(alice).transfer(chainId, airnodeId, bobClient.address, carolClient.address);
            // then:
            expect(await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            expect(await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address)).to.equal(beforeBobWhitelistCount - 1);
            // and:
            expect(await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, carolClient.address, alice.address)).to.equal(lockPeriod);
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, carolClient.address, alice.address)).to.equal(lockAmount);
            expect(await api3TokenLockExternal.tokenLocks(chainId, airnodeId, carolClient.address)).to.equal(beforeCarolWhitelistCount + 1);
          });
  
          it('emits event', async () => {
            const lockPeriod = await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address);
            const lockAmount = await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address);
            // then:
            await expect(api3TokenLockExternal.connect(alice).transfer(chainId, airnodeId, bobClient.address, carolClient.address))
              .to.emit(api3TokenLockExternal, 'Transfer')
              .withArgs(chainId, airnodeId, bobClient.address, carolClient.address, alice.address, lockAmount, lockPeriod)
              .to.emit(api3TokenLockExternal, 'Authorize')
              .withArgs(chainId, airnodeId, bobClient.address, 0)
              .to.emit(api3TokenLockExternal, 'Authorize')
              .withArgs(chainId, airnodeId, carolClient.address, ethers.constants.MaxUint256);
          });
        });
  
        context('caller has not locked amounts', async () => {
          it('reverts', async () => {
            // then:
            await expect(api3TokenLockExternal.connect(unknown).transfer(chainId, airnodeId, bobClient.address, carolClient.address))
              .to.revertedWith('locked amount must be != 0');
          });
        });
  
        context('caller toClientAddress has existing locked amount', async () => {
          it('reverts', async () => {
            // given:
            await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
            await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, carolClient.address);
            // then:
            await expect(api3TokenLockExternal.connect(alice).transfer(chainId, airnodeId, bobClient.address, carolClient.address))
              .to.revertedWith('locked amount must be 0');
          });
        });
  
        context('fromClient address is blacklisted', async () => {
          it('reverts', async () => {
            // given:
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
            // then:
            await expect(api3TokenLockExternal.connect(alice).transfer(chainId, airnodeId, bobClient.address, carolClient.address))
              .to.revertedWith(Errors.FromClientBlacklisted);
          });
        });
  
        context('toClient address is blacklisted', async () => {
          it('reverts', async () => {
            // given:
            await api3TokenLockExternal.setBlacklistStatus(carolClient.address, true);
            // then:
            await expect(api3TokenLockExternal.connect(alice).transfer(chainId, airnodeId, bobClient.address, carolClient.address))
              .to.revertedWith(Errors.ToClientBlacklisted);
          });
        });
      });
  
      describe('burn', async () => {
        beforeEach(async () => {
          // set admin
          await api3TokenLockExternal.connect(metaAdmin).setAdminStatus(admin.address, AdminStatus.Admin);
  
          // set api3 token
          await api3TokenLockExternal.connect(admin).setApi3Token(api3Token.address);
  
          // approve Api3TokenLock:
          await api3Token.connect(alice).approve(api3TokenLockExternal.address, await api3TokenLockExternal.lockAmount());
  
          // Lock:
          await api3TokenLockExternal.connect(alice).lock(chainId, airnodeId, bobClient.address);
        });
  
        context('successful burn of blacklisted client', async () => {
          beforeEach(async () => {
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, true);
          });
  
          it('burns tokens', async () => {
            const beforeTotalSupply = await api3Token.totalSupply();
            const beforeTokenLockBalance = await api3Token.balanceOf(api3TokenLockExternal.address);
            const lockAmount = await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address);
            const beforeWhitelistCount = await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address);
  
            // when:
            await api3TokenLockExternal.burn(chainId, airnodeId, bobClient.address, alice.address);
  
            // then:
            expect(await api3TokenLockExternal.canUnlockAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            expect(await api3TokenLockExternal.lockAmountAt(chainId, airnodeId, bobClient.address, alice.address)).to.equal(0);
            // and:
            expect(await api3Token.balanceOf(api3TokenLockExternal.address)).to.equal(beforeTokenLockBalance.sub(lockAmount));
            expect(await api3Token.totalSupply()).to.equal(beforeTotalSupply.sub(lockAmount));
            expect(await api3TokenLockExternal.tokenLocks(chainId, airnodeId, bobClient.address)).to.equal(beforeWhitelistCount.sub(1));
          });
  
          it('emits event', async () => {
            await expect(api3TokenLockExternal.burn(chainId, airnodeId, bobClient.address, alice.address))
              .to.emit(api3TokenLockExternal, 'Burn')
              .withArgs(chainId, airnodeId, bobClient.address, alice.address)
              .to.emit(api3TokenLockExternal, 'Authorize')
              .withArgs(chainId, airnodeId, bobClient.address, 0);
          });
        });
  
        context('burn target has zero locked amount', async () => {
          it('reverts', async () => {
            await expect(api3TokenLockExternal.burn(chainId, airnodeId, bobClient.address, unknown.address))
              .to.revertedWith(Errors.ZeroAmount);
          });
        });
  
        context('client address is not blacklisted', async () => {
          it('reverts', async () => {
            // given:
            await api3TokenLockExternal.setBlacklistStatus(bobClient.address, false);
            // then:
            await expect(api3TokenLockExternal.burn(chainId, airnodeId, bobClient.address, alice.address))
              .to.revertedWith(Errors.ClientNotBlacklisted);
          });
        });
      });
    });
  });