Add a "fees" section to the ERC4626 guide (#4054)
Co-authored-by: Francisco Giordano <fg@frang.io>
This commit is contained in:
@ -4,6 +4,7 @@ const { expect } = require('chai');
|
||||
const ERC20Decimals = artifacts.require('$ERC20DecimalsMock');
|
||||
const ERC4626 = artifacts.require('$ERC4626');
|
||||
const ERC4626OffsetMock = artifacts.require('$ERC4626OffsetMock');
|
||||
const ERC4626FeesMock = artifacts.require('$ERC4626FeesMock');
|
||||
|
||||
contract('ERC4626', function (accounts) {
|
||||
const [holder, recipient, spender, other, user1, user2] = accounts;
|
||||
@ -489,6 +490,132 @@ contract('ERC4626', function (accounts) {
|
||||
});
|
||||
}
|
||||
|
||||
describe('ERC4626Fees', function () {
|
||||
const feeBasePoint = web3.utils.toBN(5e3);
|
||||
const amountWithoutFees = web3.utils.toBN(10000);
|
||||
const fees = amountWithoutFees.mul(feeBasePoint).divn(1e5);
|
||||
const amountWithFees = amountWithoutFees.add(fees);
|
||||
|
||||
describe('input fees', function () {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC20Decimals.new(name, symbol, 18);
|
||||
this.vault = await ERC4626FeesMock.new(
|
||||
name + ' Vault',
|
||||
symbol + 'V',
|
||||
this.token.address,
|
||||
feeBasePoint,
|
||||
other,
|
||||
0,
|
||||
constants.ZERO_ADDRESS,
|
||||
);
|
||||
|
||||
await this.token.$_mint(holder, constants.MAX_INT256);
|
||||
await this.token.approve(this.vault.address, constants.MAX_INT256, { from: holder });
|
||||
});
|
||||
|
||||
it('deposit', async function () {
|
||||
expect(await this.vault.previewDeposit(amountWithFees)).to.be.bignumber.equal(amountWithoutFees);
|
||||
({ tx: this.tx } = await this.vault.deposit(amountWithFees, recipient, { from: holder }));
|
||||
});
|
||||
|
||||
it('mint', async function () {
|
||||
expect(await this.vault.previewMint(amountWithoutFees)).to.be.bignumber.equal(amountWithFees);
|
||||
({ tx: this.tx } = await this.vault.mint(amountWithoutFees, recipient, { from: holder }));
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
// get total
|
||||
await expectEvent.inTransaction(this.tx, this.token, 'Transfer', {
|
||||
from: holder,
|
||||
to: this.vault.address,
|
||||
value: amountWithFees,
|
||||
});
|
||||
|
||||
// redirect fees
|
||||
await expectEvent.inTransaction(this.tx, this.token, 'Transfer', {
|
||||
from: this.vault.address,
|
||||
to: other,
|
||||
value: fees,
|
||||
});
|
||||
|
||||
// mint shares
|
||||
await expectEvent.inTransaction(this.tx, this.vault, 'Transfer', {
|
||||
from: constants.ZERO_ADDRESS,
|
||||
to: recipient,
|
||||
value: amountWithoutFees,
|
||||
});
|
||||
|
||||
// deposit event
|
||||
await expectEvent.inTransaction(this.tx, this.vault, 'Deposit', {
|
||||
sender: holder,
|
||||
owner: recipient,
|
||||
assets: amountWithFees,
|
||||
shares: amountWithoutFees,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('output fees', function () {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC20Decimals.new(name, symbol, 18);
|
||||
this.vault = await ERC4626FeesMock.new(
|
||||
name + ' Vault',
|
||||
symbol + 'V',
|
||||
this.token.address,
|
||||
0,
|
||||
constants.ZERO_ADDRESS,
|
||||
5e3, // 5%
|
||||
other,
|
||||
);
|
||||
|
||||
await this.token.$_mint(this.vault.address, constants.MAX_INT256);
|
||||
await this.vault.$_mint(holder, constants.MAX_INT256);
|
||||
});
|
||||
|
||||
it('redeem', async function () {
|
||||
expect(await this.vault.previewRedeem(amountWithFees)).to.be.bignumber.equal(amountWithoutFees);
|
||||
({ tx: this.tx } = await this.vault.redeem(amountWithFees, recipient, holder, { from: holder }));
|
||||
});
|
||||
|
||||
it('withdraw', async function () {
|
||||
expect(await this.vault.previewWithdraw(amountWithoutFees)).to.be.bignumber.equal(amountWithFees);
|
||||
({ tx: this.tx } = await this.vault.withdraw(amountWithoutFees, recipient, holder, { from: holder }));
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
// withdraw principal
|
||||
await expectEvent.inTransaction(this.tx, this.token, 'Transfer', {
|
||||
from: this.vault.address,
|
||||
to: recipient,
|
||||
value: amountWithoutFees,
|
||||
});
|
||||
|
||||
// redirect fees
|
||||
await expectEvent.inTransaction(this.tx, this.token, 'Transfer', {
|
||||
from: this.vault.address,
|
||||
to: other,
|
||||
value: fees,
|
||||
});
|
||||
|
||||
// mint shares
|
||||
await expectEvent.inTransaction(this.tx, this.vault, 'Transfer', {
|
||||
from: holder,
|
||||
to: constants.ZERO_ADDRESS,
|
||||
value: amountWithFees,
|
||||
});
|
||||
|
||||
// withdraw event
|
||||
await expectEvent.inTransaction(this.tx, this.vault, 'Withdraw', {
|
||||
sender: holder,
|
||||
receiver: recipient,
|
||||
owner: holder,
|
||||
assets: amountWithoutFees,
|
||||
shares: amountWithFees,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/// Scenario inspired by solmate ERC4626 tests:
|
||||
/// https://github.com/transmissions11/solmate/blob/main/src/test/ERC4626.t.sol
|
||||
it('multiple mint, deposit, redeem & withdrawal', async function () {
|
||||
|
||||
Reference in New Issue
Block a user