@dydxfoundation/governance
Version:
dYdX governance smart contracts
146 lines (145 loc) • 9.72 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const utils_1 = require("ethers/lib/utils");
const config_1 = __importDefault(require("../../src/config"));
const constants_1 = require("../../src/lib/constants");
const util_1 = require("../../src/lib/util");
const describe_contract_1 = require("../helpers/describe-contract");
const keys_1 = require("../helpers/keys");
const signature_helpers_1 = require("../helpers/signature-helpers");
const hre_1 = __importDefault(require("../hre"));
const SAFETY_MODULE_EIP_712_DOMAIN_NAME = 'dYdX Safety Module';
let userKeys;
function init() {
userKeys = (0, keys_1.getUserKeys)();
}
(0, describe_contract_1.describeContract)('Safety Module Staked DYDX - ERC20 Permit', init, (ctx) => {
it('sanity check chain ID', async () => {
// Skip when forking mainnet, since these won't match.
if (!config_1.default.FORK_MAINNET) {
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const configChainId = hre_1.default.network.config.chainId;
(0, chai_1.expect)(configChainId).to.be.equal(chainId);
}
});
it('Reverts submitting a permit with 0 expiration', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const expiration = 0;
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = (0, utils_1.parseEther)('2').toString();
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, permitAmount, expiration.toFixed(), SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal('0', 'INVALID_ALLOWANCE_BEFORE_PERMIT');
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, chai_1.expect)(ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, spender, permitAmount, expiration, v, r, s)).to.be.revertedWith('INVALID_EXPIRATION');
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal('0', 'INVALID_ALLOWANCE_AFTER_PERMIT');
});
it('Submits a permit with maximum expiration length', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const deadline = constants_1.MAX_UINT_AMOUNT;
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = (0, utils_1.parseEther)('2').toString();
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, deadline, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal('0', 'INVALID_ALLOWANCE_BEFORE_PERMIT');
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, util_1.waitForTx)(await ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, spender, permitAmount, deadline, v, r, s));
(0, chai_1.expect)((await ctx.safetyModule.nonces(owner)).toNumber()).to.be.equal(1);
});
it('Cancels the previous permit', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const deadline = constants_1.MAX_UINT_AMOUNT;
{
const permitAmount = (0, utils_1.parseEther)('2').toString();
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, deadline, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal('0', 'INVALID_ALLOWANCE_BEFORE_PERMIT');
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, spender, permitAmount, deadline, v, r, s);
}
{
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = '0';
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, deadline, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal((0, utils_1.parseEther)('2'), 'INVALID_ALLOWANCE_BEFORE_PERMIT');
await (0, util_1.waitForTx)(await ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, spender, permitAmount, deadline, v, r, s));
(0, chai_1.expect)((await ctx.safetyModule.allowance(owner, spender)).toString()).to.be.equal(permitAmount, 'INVALID_ALLOWANCE_AFTER_PERMIT');
(0, chai_1.expect)((await ctx.safetyModule.nonces(owner)).toNumber()).to.be.equal(2);
}
});
it('Tries to submit a permit with invalid nonce', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const deadline = constants_1.MAX_UINT_AMOUNT;
const nonce = 1000;
const permitAmount = '0';
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, deadline, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, chai_1.expect)(ctx.safetyModule.connect(ctx.users[1]).permit(owner, spender, 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 owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const expiration = '1';
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = '0';
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, expiration, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, chai_1.expect)(ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, spender, expiration, permitAmount, v, r, s)).to.be.revertedWith('INVALID_EXPIRATION');
});
it('Tries to submit a permit with invalid signature', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const deadline = constants_1.MAX_UINT_AMOUNT;
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = '0';
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, deadline, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, chai_1.expect)(ctx.safetyModule
.connect(ctx.users[1])
.permit(owner, constants_1.ZERO_ADDRESS, permitAmount, deadline, v, r, s)).to.be.revertedWith('INVALID_SIGNATURE');
});
it('Tries to submit a permit with invalid owner', async () => {
const owner = ctx.users[0].address;
const spender = ctx.users[1].address;
const chainId = await (0, signature_helpers_1.getChainIdForSigning)();
const expiration = constants_1.MAX_UINT_AMOUNT;
const nonce = (await ctx.safetyModule.nonces(owner)).toNumber();
const permitAmount = '0';
const msgParams = (0, signature_helpers_1.buildPermitParams)(chainId, ctx.safetyModule.address, owner, spender, nonce, expiration, permitAmount, SAFETY_MODULE_EIP_712_DOMAIN_NAME);
const ownerPrivateKey = userKeys[0];
const { v, r, s } = (0, signature_helpers_1.getSignatureFromTypedData)(ownerPrivateKey, msgParams);
await (0, chai_1.expect)(ctx.safetyModule
.connect(ctx.users[1])
.permit(constants_1.ZERO_ADDRESS, spender, expiration, permitAmount, v, r, s)).to.be.revertedWith('INVALID_OWNER');
});
});