Skip to content

Commit

Permalink
feat: improved test coverage part three (#115)
Browse files Browse the repository at this point in the history
* renamed folder and changed version

* npmignore

* npmignore

* change version

* using include pattern instead.

* Fixed most of the things least auhority suggested.

* made lint happy

* Apply suggestions from code review

* fixed some bugs

* added events

* rename set to transfer for distributor and operator

* changed standardized token to always allow token managers to mint/burn it.

* using immutable storage for remoteAddressValidator address to save gas

* Added some recommended changes

* added milap's suggested changes

* Fixed some names and some minor gas optimizations

* prettier and lint

* stash

* import .env in hardhat.config

* trying to fix .env.example

* Added some getters in IRemoteAddressValidator and removed useless check for distributor in the InterchainTokenService.

* removed ternary operators

* made lint happy

* made lint happy

* Added a new token manager to handle fee on transfer and added some tests for it as well

* fixed the liquidity pool check.

* fix a duplication bug

* lint

* added some more tests

* Added more tests

* Added proper re-entrancy protection for fee on transfer token managers.

* change to tx.origin for refunds

* Added support for more kinds of addresses.

* some minor gas opts

* some more gas optimizations.

* Added a getter for chain name to the remote address validator.

* moved the tokenManager getter functionality to a separate contract which saves almost a kilobyte of codesize.

* made lint happy

* Removed tokenManagerGetter and put params into tokenManagers

* Added separate tokenManager interfaces

* addressed ackeeblockchains's 3.0 report

* prettier

* added interchain transfer methods to the service and unified receiving tokens a bit.

* made lint happy

* rename sendToken to interchainTransfer

* changed sendToken everywhere

* changed from uint256.max to a const

* change setting to zero to delete for storage slots.

* rearange storage variables to save a bit of gas.

* Removed unecesairy casts

* made as many event params inexed as possible

* Removed unused imports

* domain separator is calculated each time.

* added some natspec

* added an example for using pre-existing custom tokens.

* added a comment

* feat: improved test coverage part one

* feat: live testnet support

* fix: remove exclusive mocha test

* fix: remove hardcoded gas options

* feat: increased test coverage part two

* fix: remove comment

* feat: add test

* feat: increased test coverage part three

* fix(InvalidStandardizedToken): imports

* feat: address comments

* fix: ITS tests

* fix: tests

* fix: tests

* fix: remove broken test

* feat: add tests

* Update test/tokenService.js

---------

Co-authored-by: Foivos <[email protected]>
Co-authored-by: Milap Sheth <[email protected]>
Co-authored-by: Dean Amiel <[email protected]>
Co-authored-by: Kiryl Yermakou <[email protected]>
  • Loading branch information
5 people authored Oct 12, 2023
1 parent 59c7cae commit cde9924
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 4 deletions.
18 changes: 18 additions & 0 deletions contracts/test/utils/AddressBytesUtilsTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressBytesUtils } from '../../libraries/AddressBytesUtils.sol';

contract AddressBytesUtilsTest {
using AddressBytesUtils for address;
using AddressBytesUtils for bytes;

function toAddress(bytes memory bytesAddress) external pure returns (address addr) {
return bytesAddress.toAddress();
}

function toBytes(address addr) external pure returns (bytes memory bytesAddress) {
return addr.toBytes();
}
}
17 changes: 17 additions & 0 deletions contracts/test/utils/NoReEntrancyTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { NoReEntrancy } from '../../utils/NoReEntrancy.sol';

contract NoReEntrancyTest is NoReEntrancy {
uint256 public value;

function testFunction() external noReEntrancy {
value = 1;
this.callback();
value = 2;
}

function callback() external noReEntrancy {}
}
43 changes: 42 additions & 1 deletion test/UtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const { ethers } = require('hardhat');
const { time } = require('@nomicfoundation/hardhat-network-helpers');
const { Wallet, Contract } = ethers;
const { AddressZero } = ethers.constants;
const { defaultAbiCoder } = ethers.utils;
const { defaultAbiCoder, arrayify, toUtf8Bytes, hexlify } = ethers.utils;

const { expect } = chai;
const { getRandomBytes32, expectRevert } = require('./utils');
const { deployContract } = require('../scripts/deploy');
Expand Down Expand Up @@ -392,4 +393,44 @@ describe('StandardizedTokenDeployer', () => {
'AlreadyDeployed',
);
});

describe('AddressBytesUtils', () => {
let addressBytesUtils;

before(async () => {
addressBytesUtils = await deployContract(ownerWallet, 'AddressBytesUtilsTest');
});

it('Should convert bytes address to address', async () => {
const bytesAddress = arrayify(ownerWallet.address);
const convertedAddress = await addressBytesUtils.toAddress(bytesAddress);
expect(convertedAddress).to.eq(ownerWallet.address);
});

it('Should revert on invalid bytes length', async () => {
const bytesAddress = defaultAbiCoder.encode(['bytes'], [toUtf8Bytes(ownerWallet.address)]);
await expectRevert(
(gasOptions) => addressBytesUtils.toAddress(bytesAddress, gasOptions),
addressBytesUtils,
'InvalidBytesLength',
);
});

it('Should convert address to bytes address', async () => {
const convertedAddress = await addressBytesUtils.toBytes(ownerWallet.address);
expect(convertedAddress).to.eq(hexlify(ownerWallet.address));
});
});

describe('NoReEntrancy', () => {
let noReEntrancy;

before(async () => {
noReEntrancy = await deployContract(ownerWallet, 'NoReEntrancyTest');
});

it('Should revert on reentrancy', async function () {
await expect(noReEntrancy.testFunction()).to.be.revertedWithCustomError(noReEntrancy, 'ReEntrancy');
});
});
});
9 changes: 9 additions & 0 deletions test/standardizedToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ describe('StandardizedToken', () => {
).to.be.reverted;
});

it('should revert if standardized token setup fails', async () => {
const params = '0x1234';
await expectRevert(
(gasOptions) => deployContract(owner, 'StandardizedTokenProxy', [standardizedToken.address, params, gasOptions]),
tokenProxy,
'SetupFailed',
);
});

it('should return the correct contract ID', async () => {
const contractID = await token.contractId();
const hash = keccak256(toUtf8Bytes('standardized-token'));
Expand Down
119 changes: 119 additions & 0 deletions test/tokenManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict';

const chai = require('chai');
const { ethers } = require('hardhat');
const {
utils: { toUtf8Bytes, defaultAbiCoder },
constants: { AddressZero },
} = ethers;
const { expect } = chai;
const { expectRevert } = require('./utils');
const { deployContract } = require('../scripts/deploy');

describe('Token Manager', () => {
let owner, user, token, service, liquidityPool;
let tokenManagerLockUnlock, tokenManagerMintBurn, tokenManagerLiquidityPool, tokenManagerLockUnlockFeeOnTransfer;

before(async () => {
[owner, user, token, service, liquidityPool] = await ethers.getSigners();

tokenManagerLockUnlock = await deployContract(owner, `TokenManagerLockUnlock`, [service.address]);
tokenManagerMintBurn = await deployContract(owner, `TokenManagerMintBurn`, [service.address]);
tokenManagerLiquidityPool = await deployContract(owner, `TokenManagerLiquidityPool`, [service.address]);
tokenManagerLockUnlockFeeOnTransfer = await deployContract(owner, `TokenManagerLockUnlockFee`, [service.address]);
});

it('Should revert on token manager deployment with invalid service address', async () => {
await expectRevert(
(gasOptions) => deployContract(owner, `TokenManagerLockUnlock`, [AddressZero, gasOptions]),
tokenManagerLockUnlock,
'TokenLinkerZeroAddress',
);
});

it('Should revert on setup if not called by the proxy', async () => {
const params = '0x';
await expectRevert((gasOptions) => tokenManagerLockUnlock.setup(params, gasOptions), tokenManagerLockUnlock, 'NotProxy');
});

it('Should revert on transmitInterchainTransfer if not called by the token', async () => {
const sender = owner.address;
const destinationChain = 'Dest Chain';
const destinationAddress = toUtf8Bytes(user.address);
const amount = 10;
const metadata = '0x00000000';

await expectRevert(
(gasOptions) =>
tokenManagerLockUnlock.transmitInterchainTransfer(
sender,
destinationChain,
destinationAddress,
amount,
metadata,
gasOptions,
),
tokenManagerLockUnlock,
'NotToken',
);
});

it('Should revert on giveToken if not called by the service', async () => {
const destinationAddress = user.address;
const amount = 10;

await expectRevert(
(gasOptions) => tokenManagerLockUnlock.giveToken(destinationAddress, amount, gasOptions),
tokenManagerLockUnlock,
'NotService',
);
});

it('Should revert on takeToken if not called by the service', async () => {
const sourceAddress = user.address;
const amount = 10;

await expectRevert(
(gasOptions) => tokenManagerLockUnlock.takeToken(sourceAddress, amount, gasOptions),
tokenManagerLockUnlock,
'NotService',
);
});

it('Should revert on setFlowLimit if not called by the operator', async () => {
const flowLimit = 100;

await expectRevert(
(gasOptions) => tokenManagerLockUnlock.setFlowLimit(flowLimit, gasOptions),
tokenManagerLockUnlock,
'NotOperator',
);
});

it('Should return the correct parameters for lock/unlock token manager', async () => {
const expectedParams = defaultAbiCoder.encode(['bytes', 'address'], [toUtf8Bytes(owner.address), token.address]);
const params = await tokenManagerLockUnlock.getParams(toUtf8Bytes(owner.address), token.address);
expect(expectedParams).to.eq(params);
});

it('Should return the correct parameters for mint/burn token manager', async () => {
const expectedParams = defaultAbiCoder.encode(['bytes', 'address'], [toUtf8Bytes(owner.address), token.address]);
const params = await tokenManagerMintBurn.getParams(toUtf8Bytes(owner.address), token.address);
expect(expectedParams).to.eq(params);
});

it('Should return the correct parameters for liquidity pool token manager', async () => {
const expectedParams = defaultAbiCoder.encode(
['bytes', 'address', 'address'],
[toUtf8Bytes(owner.address), token.address, liquidityPool.address],
);
const params = await tokenManagerLiquidityPool.getParams(toUtf8Bytes(owner.address), token.address, liquidityPool.address);
expect(expectedParams).to.eq(params);
});

it('Should return the correct parameters for fee on transfer token manager', async () => {
const expectedParams = defaultAbiCoder.encode(['bytes', 'address'], [toUtf8Bytes(owner.address), token.address]);
const params = await tokenManagerLockUnlockFeeOnTransfer.getParams(toUtf8Bytes(owner.address), token.address);
expect(expectedParams).to.eq(params);
});
});
Loading

0 comments on commit cde9924

Please sign in to comment.