draft-ERC20Bridgeable.test.js 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. const { ethers } = require('hardhat');
  2. const { expect } = require('chai');
  3. const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
  4. const { shouldBehaveLikeERC20 } = require('../ERC20.behavior.js');
  5. const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
  6. const name = 'My Token';
  7. const symbol = 'MTKN';
  8. const initialSupply = 100n;
  9. async function fixture() {
  10. const [other, bridge, ...accounts] = await ethers.getSigners();
  11. const token = await ethers.deployContract('$ERC20BridgeableMock', [name, symbol, bridge]);
  12. await token.$_mint(accounts[0], initialSupply);
  13. return { bridge, other, accounts, token };
  14. }
  15. describe('ERC20Bridgeable', function () {
  16. beforeEach(async function () {
  17. Object.assign(this, await loadFixture(fixture));
  18. });
  19. describe('onlyTokenBridgeFn', function () {
  20. it('reverts when called by non-bridge', async function () {
  21. await expect(this.token.onlyTokenBridgeFn()).to.be.revertedWithCustomError(this.token, 'OnlyTokenBridge');
  22. });
  23. it('does not revert when called by bridge', async function () {
  24. await expect(this.token.connect(this.bridge).onlyTokenBridgeFn())
  25. .to.emit(this.token, 'OnlyTokenBridgeFnCalled')
  26. .withArgs(this.bridge);
  27. });
  28. });
  29. describe('crosschainMint', function () {
  30. it('reverts when called by non-bridge', async function () {
  31. await expect(this.token.crosschainMint(this.other, 100n)).to.be.revertedWithCustomError(
  32. this.token,
  33. 'OnlyTokenBridge',
  34. );
  35. });
  36. it('mints amount provided by the bridge when calling crosschainMint', async function () {
  37. const amount = 100n;
  38. await expect(this.token.connect(this.bridge).crosschainMint(this.other, amount))
  39. .to.emit(this.token, 'CrosschainMint')
  40. .withArgs(this.other, amount, this.bridge)
  41. .to.emit(this.token, 'Transfer')
  42. .withArgs(ethers.ZeroAddress, this.other, amount);
  43. await expect(this.token.balanceOf(this.other)).to.eventually.equal(amount);
  44. });
  45. });
  46. describe('crosschainBurn', function () {
  47. it('reverts when called by non-bridge', async function () {
  48. await expect(this.token.crosschainBurn(this.other, 100n)).to.be.revertedWithCustomError(
  49. this.token,
  50. 'OnlyTokenBridge',
  51. );
  52. });
  53. it('burns amount provided by the bridge when calling crosschainBurn', async function () {
  54. const amount = 100n;
  55. await this.token.$_mint(this.other, amount);
  56. await expect(this.token.connect(this.bridge).crosschainBurn(this.other, amount))
  57. .to.emit(this.token, 'CrosschainBurn')
  58. .withArgs(this.other, amount, this.bridge)
  59. .to.emit(this.token, 'Transfer')
  60. .withArgs(this.other, ethers.ZeroAddress, amount);
  61. await expect(this.token.balanceOf(this.other)).to.eventually.equal(0);
  62. });
  63. });
  64. describe('ERC165', function () {
  65. shouldSupportInterfaces({
  66. ERC7802: ['crosschainMint(address,uint256)', 'crosschainBurn(address,uint256)'],
  67. });
  68. });
  69. describe('ERC20 behavior', function () {
  70. shouldBehaveLikeERC20(initialSupply);
  71. });
  72. });