2020-09-14 13:57:11 +00:00
|
|
|
import {
|
|
|
|
MAX_UINT_AMOUNT,
|
|
|
|
ZERO_ADDRESS,
|
|
|
|
getATokenDomainSeparatorPerNetwork,
|
|
|
|
} from '../helpers/constants';
|
|
|
|
import {buildPermitParams, getSignatureFromTypedData} from '../helpers/contracts-helpers';
|
|
|
|
import {expect} from 'chai';
|
|
|
|
import {ethers} from 'ethers';
|
|
|
|
import {eEthereumNetwork} from '../helpers/types';
|
|
|
|
import {makeSuite, TestEnv} from './helpers/make-suite';
|
|
|
|
import {BRE} from '../helpers/misc-utils';
|
|
|
|
import {waitForTx} from './__setup.spec';
|
2020-09-15 15:25:34 +00:00
|
|
|
import {BUIDLEREVM_CHAINID} from '../helpers/buidler-constants';
|
2020-09-14 13:57:11 +00:00
|
|
|
|
|
|
|
const {parseEther} = ethers.utils;
|
|
|
|
|
|
|
|
makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|
|
|
it('Checks the domain separator', async () => {
|
|
|
|
const DOMAIN_SEPARATOR_ENCODED = getATokenDomainSeparatorPerNetwork(
|
|
|
|
eEthereumNetwork.buidlerevm
|
|
|
|
);
|
|
|
|
|
|
|
|
const {aDai} = testEnv;
|
|
|
|
|
|
|
|
const separator = await aDai.DOMAIN_SEPARATOR();
|
|
|
|
|
|
|
|
expect(separator).to.be.equal(DOMAIN_SEPARATOR_ENCODED, 'Invalid domain separator');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Get aDAI for tests', async () => {
|
|
|
|
const {dai, deployer, pool} = testEnv;
|
|
|
|
|
|
|
|
await dai.mint(parseEther('20000'));
|
|
|
|
await dai.approve(pool.address, parseEther('20000'));
|
|
|
|
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Reverts submitting a permit with 0 expiration', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const tokenName = await aDai.name();
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const expiration = 0;
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = ethers.utils.parseEther('2').toString();
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
tokenName,
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
permitAmount,
|
|
|
|
expiration.toFixed()
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal(
|
|
|
|
'0',
|
|
|
|
'INVALID_ALLOWANCE_BEFORE_PERMIT'
|
|
|
|
);
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, spender.address, permitAmount, expiration, v, r, s)
|
|
|
|
).to.be.revertedWith('INVALID_EXPIRATION');
|
|
|
|
|
|
|
|
expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal(
|
|
|
|
'0',
|
|
|
|
'INVALID_ALLOWANCE_AFTER_PERMIT'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Submits a permit with maximum expiration length', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = parseEther('2').toString();
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
deadline,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal(
|
|
|
|
'0',
|
|
|
|
'INVALID_ALLOWANCE_BEFORE_PERMIT'
|
|
|
|
);
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await waitForTx(
|
|
|
|
await aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, spender.address, permitAmount, deadline, v, r, s)
|
|
|
|
);
|
|
|
|
|
|
|
|
expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Cancels the previous permit', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = '0';
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
deadline,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal(
|
|
|
|
ethers.utils.parseEther('2'),
|
|
|
|
'INVALID_ALLOWANCE_BEFORE_PERMIT'
|
|
|
|
);
|
|
|
|
|
|
|
|
await waitForTx(
|
|
|
|
await aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, spender.address, permitAmount, deadline, v, r, s)
|
|
|
|
);
|
|
|
|
expect((await aDai.allowance(owner.address, spender.address)).toString()).to.be.equal(
|
|
|
|
permitAmount,
|
|
|
|
'INVALID_ALLOWANCE_AFTER_PERMIT'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect((await aDai._nonces(owner.address)).toNumber()).to.be.equal(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Tries to submit a permit with invalid nonce', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
|
|
const nonce = 1000;
|
|
|
|
const permitAmount = '0';
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
deadline,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, spender.address, permitAmount, deadline, v, r, s)
|
|
|
|
).to.be.revertedWith('INVALID_SIGNATURE');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Tries to submit a permit with invalid expiration (previous to the current block)', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const expiration = '1';
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = '0';
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
expiration,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, spender.address, expiration, permitAmount, v, r, s)
|
|
|
|
).to.be.revertedWith('INVALID_EXPIRATION');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Tries to submit a permit with invalid signature', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = '0';
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
deadline,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(owner.address, ZERO_ADDRESS, permitAmount, deadline, v, r, s)
|
|
|
|
).to.be.revertedWith('INVALID_SIGNATURE');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Tries to submit a permit with invalid owner', async () => {
|
|
|
|
const {aDai, deployer, users} = testEnv;
|
|
|
|
const owner = deployer;
|
|
|
|
const spender = users[1];
|
|
|
|
|
|
|
|
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
|
|
const expiration = MAX_UINT_AMOUNT;
|
|
|
|
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
|
|
|
const permitAmount = '0';
|
|
|
|
const msgParams = buildPermitParams(
|
|
|
|
chainId,
|
|
|
|
aDai.address,
|
|
|
|
'1',
|
|
|
|
await aDai.name(),
|
|
|
|
owner.address,
|
|
|
|
spender.address,
|
|
|
|
nonce,
|
|
|
|
expiration,
|
|
|
|
permitAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[0].secretKey;
|
|
|
|
if (!ownerPrivateKey) {
|
|
|
|
throw new Error('INVALID_OWNER_PK');
|
|
|
|
}
|
|
|
|
|
|
|
|
const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
aDai
|
|
|
|
.connect(spender.signer)
|
|
|
|
.permit(ZERO_ADDRESS, spender.address, expiration, permitAmount, v, r, s)
|
|
|
|
).to.be.revertedWith('INVALID_OWNER');
|
|
|
|
});
|
|
|
|
});
|