mirror of
https://github.com/tornadocash/tornado-pool-factory
synced 2024-02-02 15:04:08 +01:00
add creation fee logic
This commit is contained in:
parent
ecbed3dd29
commit
238363d348
@ -9,4 +9,5 @@ module.exports = {
|
||||
COMP: '0xc00e94Cb662C3520282E6f5717214004A7f26888',
|
||||
TORN: '0x77777FeDdddFfC19Ff86DB637967013e6C6A116C',
|
||||
tornWhale: '0xF977814e90dA44bFA03b6295A0616a897441aceC',
|
||||
creationFee: '200000000000000000000', // 200 TORN
|
||||
}
|
||||
|
@ -70,19 +70,25 @@ contract AddInstanceProposal {
|
||||
}
|
||||
|
||||
function denominationByIndex(uint256 _index) public view returns (uint256) {
|
||||
if (_index == 0) { return denomination0; }
|
||||
else if (_index == 1) { return denomination1; }
|
||||
else if (_index == 2) { return denomination2; }
|
||||
else {
|
||||
if (_index == 0) {
|
||||
return denomination0;
|
||||
} else if (_index == 1) {
|
||||
return denomination1;
|
||||
} else if (_index == 2) {
|
||||
return denomination2;
|
||||
} else {
|
||||
revert("Invalid instance index");
|
||||
}
|
||||
}
|
||||
|
||||
function protocolFeeByIndex(uint256 _index) public view returns (uint32) {
|
||||
if (_index == 0) { return protocolFee0; }
|
||||
else if (_index == 1) { return protocolFee1; }
|
||||
else if (_index == 2) { return protocolFee2; }
|
||||
else {
|
||||
if (_index == 0) {
|
||||
return protocolFee0;
|
||||
} else if (_index == 1) {
|
||||
return protocolFee1;
|
||||
} else if (_index == 2) {
|
||||
return protocolFee2;
|
||||
} else {
|
||||
revert("Invalid instance index");
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ contract ERC20TornadoCloneable is ERC20Tornado {
|
||||
address _token
|
||||
) external {
|
||||
require(denomination == 0 && levels == 0, "already initialized");
|
||||
|
||||
|
||||
token = IERC20(_token);
|
||||
require(_denomination > 0, "denomination should be greater than 0");
|
||||
denomination = _denomination;
|
||||
|
@ -9,22 +9,26 @@ import "@openzeppelin/contracts/proxy/Clones.sol";
|
||||
import "./ERC20TornadoCloneable.sol";
|
||||
import "./AddInstanceProposal.sol";
|
||||
import "./interfaces/IGovernance.sol";
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import { IERC20Permit } from "@openzeppelin/contracts/drafts/IERC20Permit.sol";
|
||||
|
||||
contract InstanceFactory is Ownable {
|
||||
using Clones for address;
|
||||
using Address for address;
|
||||
|
||||
address public immutable governance;
|
||||
address public immutable torn;
|
||||
address public immutable instanceRegistry;
|
||||
address public implementation;
|
||||
address public verifier;
|
||||
address public hasher;
|
||||
uint32 public merkleTreeHeight;
|
||||
uint256 public creationFee;
|
||||
|
||||
event NewVerifierSet(address indexed newVerifier);
|
||||
event NewHasherSet(address indexed newHasher);
|
||||
event NewTreeHeightSet(uint32 indexed newTreeHeight);
|
||||
event NewCreationFeeSet(uint256 indexed newCreationFee);
|
||||
event NewImplementationSet(address indexed newImplemenentation);
|
||||
event NewInstanceCloneCreated(address indexed clone);
|
||||
event NewGovernanceProposalCreated(address indexed proposal);
|
||||
@ -34,13 +38,17 @@ contract InstanceFactory is Ownable {
|
||||
address _hasher,
|
||||
uint32 _merkleTreeHeight,
|
||||
address _governance,
|
||||
address _instanceRegistry
|
||||
address _instanceRegistry,
|
||||
address _torn,
|
||||
uint256 _creationFee
|
||||
) {
|
||||
verifier = _verifier;
|
||||
hasher = _hasher;
|
||||
merkleTreeHeight = _merkleTreeHeight;
|
||||
governance = _governance;
|
||||
instanceRegistry = _instanceRegistry;
|
||||
torn = _torn;
|
||||
creationFee = _creationFee;
|
||||
|
||||
ERC20TornadoCloneable implContract = new ERC20TornadoCloneable(_verifier, _hasher);
|
||||
implementation = address(implContract);
|
||||
@ -65,25 +73,46 @@ contract InstanceFactory is Ownable {
|
||||
return implementation.predictDeterministicAddress(salt);
|
||||
}
|
||||
|
||||
function createNewProposal(
|
||||
function createProposalApprove(
|
||||
address _token,
|
||||
uint24 _uniswapPoolSwappingFee,
|
||||
uint256[] memory _denominations,
|
||||
uint32[] memory _protocolFees
|
||||
) external returns (address) {
|
||||
require(IERC20(torn).transferFrom(msg.sender, governance, creationFee));
|
||||
return _createProposal(_token, _uniswapPoolSwappingFee, _denominations, _protocolFees);
|
||||
}
|
||||
|
||||
function createProposalPermit(
|
||||
address _token,
|
||||
uint24 _uniswapPoolSwappingFee,
|
||||
uint256[] memory _denominations,
|
||||
uint32[] memory _protocolFees,
|
||||
address creater,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external returns (address) {
|
||||
IERC20Permit(torn).permit(creater, address(this), creationFee, deadline, v, r, s);
|
||||
require(IERC20(torn).transferFrom(creater, governance, creationFee));
|
||||
return _createProposal(_token, _uniswapPoolSwappingFee, _denominations, _protocolFees);
|
||||
}
|
||||
|
||||
function _createProposal(
|
||||
address _token,
|
||||
uint24 _uniswapPoolSwappingFee,
|
||||
uint256[] memory _denominations,
|
||||
uint32[] memory _protocolFees
|
||||
) internal returns (address) {
|
||||
require(_token.isContract(), "Token is not contract"); // TODO should we check that such instance already exist?
|
||||
require(_uniswapPoolSwappingFee > 0, "uniswapPoolSwappingFee is zero"); // TODO should we check > 0 ?
|
||||
require(_denominations.length > 0, "Empty denominations");
|
||||
require(_denominations.length == _protocolFees.length, "Incorrect denominations/fees length");
|
||||
|
||||
address proposal = address(new AddInstanceProposal(
|
||||
address(this),
|
||||
instanceRegistry,
|
||||
_token,
|
||||
_uniswapPoolSwappingFee,
|
||||
_denominations,
|
||||
_protocolFees
|
||||
));
|
||||
address proposal = address(
|
||||
new AddInstanceProposal(address(this), instanceRegistry, _token, _uniswapPoolSwappingFee, _denominations, _protocolFees)
|
||||
);
|
||||
emit NewGovernanceProposalCreated(proposal);
|
||||
|
||||
return proposal;
|
||||
@ -104,6 +133,11 @@ contract InstanceFactory is Ownable {
|
||||
emit NewTreeHeightSet(merkleTreeHeight);
|
||||
}
|
||||
|
||||
function setCreationFee(uint256 _creationFee) external onlyOwner {
|
||||
creationFee = _creationFee;
|
||||
emit NewCreationFeeSet(_creationFee);
|
||||
}
|
||||
|
||||
function setImplementation(address _newImplementation) external onlyOwner {
|
||||
implementation = _newImplementation;
|
||||
emit NewImplementationSet(implementation);
|
||||
|
@ -6,8 +6,10 @@ pragma abicoder v2;
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
interface IInstanceRegistry {
|
||||
|
||||
enum InstanceState { DISABLED, ENABLED}
|
||||
enum InstanceState {
|
||||
DISABLED,
|
||||
ENABLED
|
||||
}
|
||||
|
||||
struct Instance {
|
||||
bool isERC20;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity 0.6.12 || 0.7.6;
|
||||
pragma solidity 0.6.12||0.7.6;
|
||||
|
||||
import { Governance } from "tornado-governance/contracts/v1/Governance.sol";
|
||||
import { InstanceRegistry } from "tornado-relayer-registry/contracts/tornado-proxy/InstanceRegistry.sol";
|
||||
|
44
scripts/permit.js
Normal file
44
scripts/permit.js
Normal file
@ -0,0 +1,44 @@
|
||||
const { EIP712Signer } = require('@ticket721/e712')
|
||||
|
||||
const Permit = [
|
||||
{ name: 'owner', type: 'address' },
|
||||
{ name: 'spender', type: 'address' },
|
||||
{ name: 'value', type: 'uint256' },
|
||||
{ name: 'nonce', type: 'uint256' },
|
||||
{ name: 'deadline', type: 'uint256' },
|
||||
]
|
||||
|
||||
class PermitSigner extends EIP712Signer {
|
||||
constructor(_domain, _permitArgs) {
|
||||
super(_domain, ['Permit', Permit])
|
||||
this.permitArgs = _permitArgs
|
||||
}
|
||||
|
||||
// Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)
|
||||
setPermitInfo(_permitArgs) {
|
||||
this.permitArgs = _permitArgs
|
||||
}
|
||||
|
||||
getPayload() {
|
||||
return this.generatePayload(this.permitArgs, 'Permit')
|
||||
}
|
||||
|
||||
async getSignature(privateKey) {
|
||||
let payload = this.getPayload()
|
||||
payload.message.owner = payload.message.owner.address
|
||||
const { hex, v, r, s } = await this.sign(privateKey, payload)
|
||||
return {
|
||||
hex,
|
||||
v,
|
||||
r: '0x' + r,
|
||||
s: '0x' + s,
|
||||
}
|
||||
}
|
||||
|
||||
getSignerAddress(permitArgs, signature) {
|
||||
const original_payload = this.generatePayload(permitArgs, 'Permit')
|
||||
return this.verify(original_payload, signature)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { PermitSigner }
|
@ -7,7 +7,7 @@ const { rbigint, createDeposit, toHex, generateProof, initialize } = require('to
|
||||
const MixerContractABI = require('tornado-cli/build/contracts/Mixer.abi.json')
|
||||
const config = require('../config')
|
||||
const { getSignerFromAddress, minewait } = require('./utils')
|
||||
|
||||
const { PermitSigner } = require('../scripts/permit.js')
|
||||
|
||||
describe('Instance Factory Tests', () => {
|
||||
const ProposalState = {
|
||||
@ -26,14 +26,11 @@ describe('Instance Factory Tests', () => {
|
||||
const [sender, deployer, multisig] = await ethers.getSigners()
|
||||
|
||||
const tornWhale = await getSignerFromAddress(config.tornWhale)
|
||||
|
||||
const gov = await ethers.getContractAt(
|
||||
'Governance',
|
||||
config.governance,
|
||||
)
|
||||
|
||||
const gov = await ethers.getContractAt('Governance', config.governance)
|
||||
|
||||
const tornToken = await ethers.getContractAt(
|
||||
'@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20',
|
||||
'@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20',
|
||||
config.TORN,
|
||||
)
|
||||
|
||||
@ -43,7 +40,7 @@ describe('Instance Factory Tests', () => {
|
||||
)
|
||||
|
||||
instanceRegistry = await ethers.getContractAt(
|
||||
'tornado-relayer-registry/contracts/tornado-proxy/InstanceRegistry.sol:InstanceRegistry',
|
||||
'tornado-relayer-registry/contracts/tornado-proxy/InstanceRegistry.sol:InstanceRegistry',
|
||||
config.instanceRegistry,
|
||||
)
|
||||
|
||||
@ -54,11 +51,23 @@ describe('Instance Factory Tests', () => {
|
||||
config.hasher,
|
||||
config.merkleTreeHeight,
|
||||
config.governance,
|
||||
config.instanceRegistry
|
||||
config.instanceRegistry,
|
||||
config.TORN,
|
||||
config.creationFee,
|
||||
)
|
||||
await instanceFactory.deployed()
|
||||
|
||||
return { sender, deployer, multisig, tornWhale, gov, tornToken, compToken, instanceRegistry, instanceFactory }
|
||||
return {
|
||||
sender,
|
||||
deployer,
|
||||
multisig,
|
||||
tornWhale,
|
||||
gov,
|
||||
tornToken,
|
||||
compToken,
|
||||
instanceRegistry,
|
||||
instanceFactory,
|
||||
}
|
||||
}
|
||||
|
||||
it('Should have initialized all successfully', async function () {
|
||||
@ -73,11 +82,13 @@ describe('Instance Factory Tests', () => {
|
||||
it('Should set correct params for factory', async function () {
|
||||
const { instanceFactory } = await loadFixture(fixture)
|
||||
|
||||
expect( await instanceFactory.governance()).to.be.equal(config.governance)
|
||||
expect( await instanceFactory.verifier()).to.be.equal(config.verifier)
|
||||
expect( await instanceFactory.hasher()).to.be.equal(config.hasher)
|
||||
expect( await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
||||
expect(await instanceFactory.governance()).to.be.equal(config.governance)
|
||||
expect(await instanceFactory.verifier()).to.be.equal(config.verifier)
|
||||
expect(await instanceFactory.hasher()).to.be.equal(config.hasher)
|
||||
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
||||
expect(await instanceFactory.implementation()).to.exist
|
||||
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
||||
expect(await instanceFactory.torn()).to.be.equal(config.TORN)
|
||||
})
|
||||
|
||||
it('Governance should be able to set factory params', async function () {
|
||||
@ -87,48 +98,58 @@ describe('Instance Factory Tests', () => {
|
||||
|
||||
const govSigner = await getSignerFromAddress(gov.address)
|
||||
instanceFactory = await instanceFactory.connect(govSigner)
|
||||
|
||||
|
||||
await instanceFactory.setVerifier(addressZero)
|
||||
await instanceFactory.setHasher(addressZero)
|
||||
await instanceFactory.setMerkleTreeHeight(1)
|
||||
await instanceFactory.setCreationFee(0)
|
||||
|
||||
expect( await instanceFactory.verifier()).to.be.equal(addressZero)
|
||||
expect( await instanceFactory.hasher()).to.be.equal(addressZero)
|
||||
expect( await instanceFactory.merkleTreeHeight()).to.be.equal(1)
|
||||
expect(await instanceFactory.verifier()).to.be.equal(addressZero)
|
||||
expect(await instanceFactory.hasher()).to.be.equal(addressZero)
|
||||
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(1)
|
||||
expect(await instanceFactory.creationFee()).to.be.equal(0)
|
||||
|
||||
await instanceFactory.setVerifier(config.verifier)
|
||||
await instanceFactory.setHasher(config.hasher)
|
||||
await instanceFactory.setMerkleTreeHeight(config.merkleTreeHeight)
|
||||
await instanceFactory.setCreationFee(config.creationFee)
|
||||
|
||||
expect( await instanceFactory.verifier()).to.be.equal(config.verifier)
|
||||
expect( await instanceFactory.hasher()).to.be.equal(config.hasher)
|
||||
expect( await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
||||
expect(await instanceFactory.verifier()).to.be.equal(config.verifier)
|
||||
expect(await instanceFactory.hasher()).to.be.equal(config.hasher)
|
||||
expect(await instanceFactory.merkleTreeHeight()).to.be.equal(config.merkleTreeHeight)
|
||||
expect(await instanceFactory.creationFee()).to.be.equal(config.creationFee)
|
||||
})
|
||||
|
||||
it('Should successfully deploy/propose/execute proposal - add instance', async function () {
|
||||
let { instanceFactory, gov, instanceRegistry, tornWhale, tornToken } = await loadFixture(fixture)
|
||||
let { sender, instanceFactory, gov, instanceRegistry, tornWhale, tornToken } = await loadFixture(fixture)
|
||||
|
||||
// deploy proposal ----------------------------------------------
|
||||
let tx = await instanceFactory.createNewProposal(
|
||||
config.COMP,
|
||||
3000,
|
||||
[ethers.utils.parseEther('100')],
|
||||
[30]
|
||||
)
|
||||
let receipt = await tx.wait()
|
||||
await tornToken.connect(tornWhale).transfer(sender.address, config.creationFee)
|
||||
await tornToken.approve(instanceFactory.address, config.creationFee)
|
||||
|
||||
const proposal = await ethers.getContractAt(
|
||||
'AddInstanceProposal',
|
||||
receipt.events[0].args[0],
|
||||
await expect(() =>
|
||||
instanceFactory
|
||||
.connect(sender)
|
||||
.createProposalApprove(config.COMP, 3000, [ethers.utils.parseEther('100')], [30]),
|
||||
).to.changeTokenBalances(
|
||||
tornToken,
|
||||
[sender, gov],
|
||||
[BigNumber.from(0).sub(config.creationFee), config.creationFee],
|
||||
)
|
||||
|
||||
expect( await proposal.instanceFactory()).to.be.equal(instanceFactory.address)
|
||||
expect( await proposal.instanceRegistry()).to.be.equal(instanceRegistry.address)
|
||||
expect( await proposal.token()).to.be.equal(config.COMP)
|
||||
expect( await proposal.uniswapPoolSwappingFee()).to.be.equal(3000)
|
||||
expect( await proposal.numInstances()).to.be.equal(1)
|
||||
expect( await proposal.protocolFeeByIndex(0)).to.be.equal(30)
|
||||
expect( await proposal.denominationByIndex(0)).to.be.equal(ethers.utils.parseEther('100'))
|
||||
|
||||
let logs = await ethers.provider.getLogs(instanceFactory.filters.NewGovernanceProposalCreated())
|
||||
const proposal = await ethers.getContractAt(
|
||||
'AddInstanceProposal',
|
||||
ethers.utils.getAddress('0x' + logs[0].topics[1].slice(26)),
|
||||
)
|
||||
|
||||
expect(await proposal.instanceFactory()).to.be.equal(instanceFactory.address)
|
||||
expect(await proposal.instanceRegistry()).to.be.equal(instanceRegistry.address)
|
||||
expect(await proposal.token()).to.be.equal(config.COMP)
|
||||
expect(await proposal.uniswapPoolSwappingFee()).to.be.equal(3000)
|
||||
expect(await proposal.numInstances()).to.be.equal(1)
|
||||
expect(await proposal.protocolFeeByIndex(0)).to.be.equal(30)
|
||||
expect(await proposal.denominationByIndex(0)).to.be.equal(ethers.utils.parseEther('100'))
|
||||
|
||||
// propose proposal ---------------------------------------------
|
||||
let response, id, state
|
||||
@ -147,7 +168,7 @@ describe('Instance Factory Tests', () => {
|
||||
expect(args.target).to.be.equal(proposal.address)
|
||||
expect(args.description).to.be.equal('COMP token instance proposal')
|
||||
expect(state).to.be.equal(ProposalState.Pending)
|
||||
|
||||
|
||||
// execute proposal ---------------------------------------------
|
||||
await minewait((await gov.VOTING_DELAY()).add(1).toNumber())
|
||||
await expect(gov.castVote(id, true)).to.not.be.reverted
|
||||
@ -161,7 +182,7 @@ describe('Instance Factory Tests', () => {
|
||||
.toNumber(),
|
||||
)
|
||||
expect(await gov.state(id)).to.be.equal(ProposalState.AwaitingExecution)
|
||||
|
||||
|
||||
tx = await gov.execute(id)
|
||||
|
||||
expect(await gov.state(id)).to.be.equal(ProposalState.Executed)
|
||||
@ -169,25 +190,92 @@ describe('Instance Factory Tests', () => {
|
||||
// check instance initialization --------------------------------
|
||||
receipt = await tx.wait()
|
||||
const instanceAddr = '0x' + receipt.events[0].topics[1].toString().slice(-40)
|
||||
const instance = await ethers.getContractAt(
|
||||
'ERC20TornadoCloneable',
|
||||
instanceAddr,
|
||||
)
|
||||
const instance = await ethers.getContractAt('ERC20TornadoCloneable', instanceAddr)
|
||||
|
||||
expect( await instance.token()).to.be.equal(config.COMP)
|
||||
expect( await instance.verifier()).to.be.equal(config.verifier)
|
||||
expect( await instance.hasher()).to.be.equal(config.hasher)
|
||||
expect( await instance.levels()).to.be.equal(config.merkleTreeHeight)
|
||||
expect( await instance.denomination()).to.equal(ethers.utils.parseEther('100'))
|
||||
expect(await instance.token()).to.be.equal(config.COMP)
|
||||
expect(await instance.verifier()).to.be.equal(config.verifier)
|
||||
expect(await instance.hasher()).to.be.equal(config.hasher)
|
||||
expect(await instance.levels()).to.be.equal(config.merkleTreeHeight)
|
||||
expect(await instance.denomination()).to.equal(ethers.utils.parseEther('100'))
|
||||
|
||||
const instanceData = await instanceRegistry.instances(instance.address)
|
||||
const instanceData = await instanceRegistry.instances(instance.address)
|
||||
expect(instanceData.isERC20).to.be.equal(true)
|
||||
expect(instanceData.token).to.be.equal(config.COMP)
|
||||
expect(instanceData.state).to.be.equal(1)
|
||||
expect(instanceData.uniswapPoolSwappingFee).to.be.equal(3000)
|
||||
expect(instanceData.protocolFeePercentage).to.be.equal(30)
|
||||
})
|
||||
|
||||
|
||||
it('Should successfully deploy proposal with permit', async function () {
|
||||
let { instanceFactory, gov, instanceRegistry, tornWhale, tornToken } = await loadFixture(fixture)
|
||||
|
||||
const privateKey = '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3'
|
||||
const publicKey = '0x' + ethers.utils.computeAddress(Buffer.from(privateKey.slice(2), 'hex'))
|
||||
const sender = await ethers.getSigner(publicKey.slice(2))
|
||||
|
||||
await expect(() =>
|
||||
tornToken.connect(tornWhale).transfer(sender.address, config.creationFee),
|
||||
).to.changeTokenBalances(
|
||||
tornToken,
|
||||
[tornWhale, sender],
|
||||
[BigNumber.from(0).sub(config.creationFee), config.creationFee],
|
||||
)
|
||||
|
||||
// prepare permit data
|
||||
const domain = {
|
||||
name: await tornToken.name(),
|
||||
version: '1',
|
||||
chainId: 1,
|
||||
verifyingContract: tornToken.address,
|
||||
}
|
||||
|
||||
const curTimestamp = Math.trunc(new Date().getTime() / 1000)
|
||||
const args = {
|
||||
owner: sender,
|
||||
spender: instanceFactory.address,
|
||||
value: config.creationFee,
|
||||
nonce: 0,
|
||||
deadline: curTimestamp + 1000,
|
||||
}
|
||||
|
||||
const permitSigner = new PermitSigner(domain, args)
|
||||
const signature = await permitSigner.getSignature(privateKey)
|
||||
const signer = await permitSigner.getSignerAddress(args, signature.hex)
|
||||
expect(signer).to.equal(sender.address)
|
||||
|
||||
await expect(() =>
|
||||
instanceFactory.createProposalPermit(
|
||||
config.COMP,
|
||||
3000,
|
||||
[ethers.utils.parseEther('100')],
|
||||
[30],
|
||||
sender.address,
|
||||
args.deadline.toString(),
|
||||
signature.v,
|
||||
signature.r,
|
||||
signature.s,
|
||||
),
|
||||
).to.changeTokenBalances(
|
||||
tornToken,
|
||||
[sender, gov],
|
||||
[BigNumber.from(0).sub(config.creationFee), config.creationFee],
|
||||
)
|
||||
|
||||
let logs = await ethers.provider.getLogs(instanceFactory.filters.NewGovernanceProposalCreated())
|
||||
const proposal = await ethers.getContractAt(
|
||||
'AddInstanceProposal',
|
||||
ethers.utils.getAddress('0x' + logs[0].topics[1].slice(26)),
|
||||
)
|
||||
|
||||
expect(await proposal.instanceFactory()).to.be.equal(instanceFactory.address)
|
||||
expect(await proposal.instanceRegistry()).to.be.equal(instanceRegistry.address)
|
||||
expect(await proposal.token()).to.be.equal(config.COMP)
|
||||
expect(await proposal.uniswapPoolSwappingFee()).to.be.equal(3000)
|
||||
expect(await proposal.numInstances()).to.be.equal(1)
|
||||
expect(await proposal.protocolFeeByIndex(0)).to.be.equal(30)
|
||||
expect(await proposal.denominationByIndex(0)).to.be.equal(ethers.utils.parseEther('100'))
|
||||
})
|
||||
|
||||
// it('Should prepare data for instance deposit/withdraw tests', async () => {
|
||||
// const RAITokenAddress = '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919'
|
||||
// await sendr('hardhat_impersonateAccount', ['0x46a0B4Fa58141ABa23185e79f7047A7dFd0FF100'])
|
||||
|
Loading…
Reference in New Issue
Block a user