123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- /* eslint-disable */
- const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
- const { expect } = require('chai');
- const { MAX_UINT256, ZERO_ADDRESS } = constants;
- const ERC20FlashMintMock = artifacts.require('$ERC20FlashMintMock');
- const ERC3156FlashBorrowerMock = artifacts.require('ERC3156FlashBorrowerMock');
- contract('ERC20FlashMint', function (accounts) {
- const [initialHolder, other, anotherAccount] = accounts;
- const name = 'My Token';
- const symbol = 'MTKN';
- const initialSupply = new BN(100);
- const loanAmount = new BN(10000000000000);
- beforeEach(async function () {
- this.token = await ERC20FlashMintMock.new(name, symbol);
- await this.token.$_mint(initialHolder, initialSupply);
- });
- describe('maxFlashLoan', function () {
- it('token match', async function () {
- expect(await this.token.maxFlashLoan(this.token.address)).to.be.bignumber.equal(MAX_UINT256.sub(initialSupply));
- });
- it('token mismatch', async function () {
- expect(await this.token.maxFlashLoan(ZERO_ADDRESS)).to.be.bignumber.equal('0');
- });
- });
- describe('flashFee', function () {
- it('token match', async function () {
- expect(await this.token.flashFee(this.token.address, loanAmount)).to.be.bignumber.equal('0');
- });
- it('token mismatch', async function () {
- await expectRevert(this.token.flashFee(ZERO_ADDRESS, loanAmount), 'ERC20FlashMint: wrong token');
- });
- });
- describe('flashFeeReceiver', function () {
- it('default receiver', async function () {
- expect(await this.token.$_flashFeeReceiver()).to.be.eq(ZERO_ADDRESS);
- });
- });
- describe('flashLoan', function () {
- it('success', async function () {
- const receiver = await ERC3156FlashBorrowerMock.new(true, true);
- const { tx } = await this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x');
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: ZERO_ADDRESS,
- to: receiver.address,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: receiver.address,
- to: ZERO_ADDRESS,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, receiver, 'BalanceOf', {
- token: this.token.address,
- account: receiver.address,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, receiver, 'TotalSupply', {
- token: this.token.address,
- value: initialSupply.add(loanAmount),
- });
- expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply);
- expect(await this.token.balanceOf(receiver.address)).to.be.bignumber.equal('0');
- expect(await this.token.allowance(receiver.address, this.token.address)).to.be.bignumber.equal('0');
- });
- it('missing return value', async function () {
- const receiver = await ERC3156FlashBorrowerMock.new(false, true);
- await expectRevert(
- this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x'),
- 'ERC20FlashMint: invalid return value',
- );
- });
- it('missing approval', async function () {
- const receiver = await ERC3156FlashBorrowerMock.new(true, false);
- await expectRevert(
- this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x'),
- 'ERC20: insufficient allowance',
- );
- });
- it('unavailable funds', async function () {
- const receiver = await ERC3156FlashBorrowerMock.new(true, true);
- const data = this.token.contract.methods.transfer(other, 10).encodeABI();
- await expectRevert(
- this.token.flashLoan(receiver.address, this.token.address, loanAmount, data),
- 'ERC20: burn amount exceeds balance',
- );
- });
- it('more than maxFlashLoan', async function () {
- const receiver = await ERC3156FlashBorrowerMock.new(true, true);
- const data = this.token.contract.methods.transfer(other, 10).encodeABI();
- // _mint overflow reverts using a panic code. No reason string.
- await expectRevert.unspecified(this.token.flashLoan(receiver.address, this.token.address, MAX_UINT256, data));
- });
- describe('custom flash fee & custom fee receiver', function () {
- const receiverInitialBalance = new BN(200000);
- const flashFee = new BN(5000);
- beforeEach('init receiver balance & set flash fee', async function () {
- this.receiver = await ERC3156FlashBorrowerMock.new(true, true);
- const receipt = await this.token.$_mint(this.receiver.address, receiverInitialBalance);
- await expectEvent(receipt, 'Transfer', {
- from: ZERO_ADDRESS,
- to: this.receiver.address,
- value: receiverInitialBalance,
- });
- expect(await this.token.balanceOf(this.receiver.address)).to.be.bignumber.equal(receiverInitialBalance);
- await this.token.setFlashFee(flashFee);
- expect(await this.token.flashFee(this.token.address, loanAmount)).to.be.bignumber.equal(flashFee);
- });
- it('default flash fee receiver', async function () {
- const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanAmount, '0x');
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: ZERO_ADDRESS,
- to: this.receiver.address,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: this.receiver.address,
- to: ZERO_ADDRESS,
- value: loanAmount.add(flashFee),
- });
- await expectEvent.inTransaction(tx, this.receiver, 'BalanceOf', {
- token: this.token.address,
- account: this.receiver.address,
- value: receiverInitialBalance.add(loanAmount),
- });
- await expectEvent.inTransaction(tx, this.receiver, 'TotalSupply', {
- token: this.token.address,
- value: initialSupply.add(receiverInitialBalance).add(loanAmount),
- });
- expect(await this.token.totalSupply()).to.be.bignumber.equal(
- initialSupply.add(receiverInitialBalance).sub(flashFee),
- );
- expect(await this.token.balanceOf(this.receiver.address)).to.be.bignumber.equal(
- receiverInitialBalance.sub(flashFee),
- );
- expect(await this.token.balanceOf(await this.token.$_flashFeeReceiver())).to.be.bignumber.equal('0');
- expect(await this.token.allowance(this.receiver.address, this.token.address)).to.be.bignumber.equal('0');
- });
- it('custom flash fee receiver', async function () {
- const flashFeeReceiverAddress = anotherAccount;
- await this.token.setFlashFeeReceiver(flashFeeReceiverAddress);
- expect(await this.token.$_flashFeeReceiver()).to.be.eq(flashFeeReceiverAddress);
- expect(await this.token.balanceOf(flashFeeReceiverAddress)).to.be.bignumber.equal('0');
- const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanAmount, '0x');
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: ZERO_ADDRESS,
- to: this.receiver.address,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: this.receiver.address,
- to: ZERO_ADDRESS,
- value: loanAmount,
- });
- await expectEvent.inTransaction(tx, this.token, 'Transfer', {
- from: this.receiver.address,
- to: flashFeeReceiverAddress,
- value: flashFee,
- });
- await expectEvent.inTransaction(tx, this.receiver, 'BalanceOf', {
- token: this.token.address,
- account: this.receiver.address,
- value: receiverInitialBalance.add(loanAmount),
- });
- await expectEvent.inTransaction(tx, this.receiver, 'TotalSupply', {
- token: this.token.address,
- value: initialSupply.add(receiverInitialBalance).add(loanAmount),
- });
- expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply.add(receiverInitialBalance));
- expect(await this.token.balanceOf(this.receiver.address)).to.be.bignumber.equal(
- receiverInitialBalance.sub(flashFee),
- );
- expect(await this.token.balanceOf(flashFeeReceiverAddress)).to.be.bignumber.equal(flashFee);
- expect(await this.token.allowance(this.receiver.address, flashFeeReceiverAddress)).to.be.bignumber.equal('0');
- });
- });
- });
- });
|