@ -51,31 +51,37 @@ describe('Instance Factory With Registry Tests', () => {
config . instanceRegistry ,
)
// deploy Instance FactoryWithRegistry with CREATE2
// deploy Instance ProposalCreator with CREATE2
const singletonFactory = await ethers . getContractAt (
'SingletonFactory' ,
config . singletonFactoryVerboseWrapper ,
)
const contracts = await generate ( )
if (
( await ethers . provider . getCode ( contracts . factoryWithRegistryContract . implementation . address ) ) == '0x'
) {
await singletonFactory . deploy (
contracts . factoryWithRegistryContract . implementation . bytecode ,
config . salt ,
{
gasLimit : config . deployGasLimit ,
} ,
)
if ( ( await ethers . provider . getCode ( contracts . factory . implementation . address ) ) == '0x' ) {
await singletonFactory . deploy ( contracts . factory . implementation . bytecode , config . salt , {
gasLimit : config . deployGasLimit ,
} )
}
if ( ( await ethers . provider . getCode ( contracts . factory . proxy . address ) ) == '0x' ) {
await singletonFactory . deploy ( contracts . factory . proxy . bytecode , config . salt , {
gasLimit : config . deployGasLimit ,
} )
}
const instanceFactory = await ethers . getContractAt ( 'InstanceFactory' , contracts . factory . proxy . address )
if ( ( await ethers . provider . getCode ( contracts . proposalCreator . implementation . address ) ) == '0x' ) {
await singletonFactory . deploy ( contracts . proposalCreator . implementation . bytecode , config . salt , {
gasLimit : config . deployGasLimit ,
} )
}
if ( ( await ethers . provider . getCode ( contracts . factoryWithRegistryContract . proxy . address ) ) == '0x' ) {
await singletonFactory . deploy ( contracts . factoryWithRegistryContract . proxy . bytecode , config . salt , {
if ( ( await ethers . provider . getCode ( contracts . proposalCreator . proxy . address ) ) == '0x' ) {
await singletonFactory . deploy ( contracts . proposalCreator . proxy . bytecode , config . salt , {
gasLimit : config . deployGasLimit ,
} )
}
const instanceFactory = await ethers . getContractAt (
'Instance FactoryWithRegistry ',
contracts . factoryWithRegistryContract . proxy . address ,
const proposalCreator = await ethers . getContractAt (
'Instance ProposalCreator ',
contracts . proposalCreator . proxy . address ,
)
return {
@ -90,73 +96,80 @@ describe('Instance Factory With Registry Tests', () => {
compToken ,
instanceRegistry ,
instanceFactory ,
proposalCreator ,
}
}
it ( 'Should have initialized all successfully' , async function ( ) {
const { sender , gov , tornToken , instanceRegistry , instanceFactory } = await loadFixture ( fixture )
const { sender , gov , tornToken , instanceRegistry , instanceFactory , proposalCreator } = await loadFixture (
fixture ,
)
expect ( sender . address ) . to . exist
expect ( gov . address ) . to . exist
expect ( tornToken . address ) . to . exist
expect ( instanceRegistry . address ) . to . exist
expect ( instanceFactory . address ) . to . exist
expect ( proposalCreator . address ) . to . exist
} )
it ( 'Should set correct params for factory' , async function ( ) {
const { instanceFactory } = await loadFixture ( fixture )
const { instanceFactory , proposalCreator } = await loadFixture ( fixture )
expect ( await instanceFactory . governance ( ) ) . to . be . equal ( config . governance )
expect ( await proposalCreator . 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 )
expect ( await instanceFactory . TWAPSlotsMin ( ) ) . to . be . equal ( config . TWAPSlotsMin )
expect ( await instanceFactory . WETH ( ) ) . to . be . equal ( config . WETH )
expect ( await instanceFactory . UniswapV3Factory ( ) ) . to . be . equal ( config . UniswapV3Factory )
expect ( await instanceFactory . ERC20Impl ( ) ) . to . exist
expect ( await instanceFactory . nativeCurImpl ( ) ) . to . exist
expect ( await proposalCreator . creationFee ( ) ) . to . be . equal ( config . creationFee )
expect ( await proposalCreator . torn ( ) ) . to . be . equal ( config . TORN )
expect ( await proposalCreator . TWAPSlotsMin ( ) ) . to . be . equal ( config . TWAPSlotsMin )
expect ( await proposalCreator . WETH ( ) ) . to . be . equal ( config . WETH )
expect ( await proposalCreator . UniswapV3Factory ( ) ) . to . be . equal ( config . UniswapV3Factory )
} )
it ( 'Governance should be able to set factory params', async function ( ) {
let { instanceFactory , gov } = await loadFixture ( fixture )
it ( 'Governance should be able to set factory /proposalCreator params', async function ( ) {
let { instanceFactory , proposalCreator, gov } = await loadFixture ( fixture )
await expect ( instanceFactory . setMerkleTreeHeight ( 1 ) ) . to . be . reverted
const govSigner = await getSignerFromAddress ( gov . address )
instanceFactory = await instanceFactory . connect ( govSigner )
proposalCreator = await proposalCreator . connect ( govSigner )
await instanceFactory . generateNewImplementation ( addressZero , addressZero )
await instanceFactory . setMerkleTreeHeight ( 1 )
await instanceFactory . setCreationFee ( 0 )
await instanceFactory . setTWAPSlotsMin ( 0 )
await proposalCreator . setCreationFee ( 0 )
await proposalCreator . setTWAPSlotsMin ( 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 . creationFee ( ) ) . to . be . equal ( 0 )
expect ( await instanceFactory . TWAPSlotsMin ( ) ) . to . be . equal ( 0 )
expect ( await proposalCreator . creationFee ( ) ) . to . be . equal ( 0 )
expect ( await proposalCreator . TWAPSlotsMin ( ) ) . to . be . equal ( 0 )
await instanceFactory . generateNewImplementation ( config . verifier , config . hasher )
await instanceFactory . setMerkleTreeHeight ( config . merkleTreeHeight )
await instanceFactory . setCreationFee ( config . creationFee )
await instanceFactory . setTWAPSlotsMin ( config . TWAPSlotsMin )
await proposalCreator . setCreationFee ( config . creationFee )
await proposalCreator . setTWAPSlotsMin ( config . TWAPSlotsMin )
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 )
expect ( await instanceFactory . TWAPSlotsMin ( ) ) . to . be . equal ( config . TWAPSlotsMin )
expect ( await proposalCreator . creationFee ( ) ) . to . be . equal ( config . creationFee )
expect ( await proposalCreator . TWAPSlotsMin ( ) ) . to . be . equal ( config . TWAPSlotsMin )
} )
it ( 'Should successfully deploy/propose/execute proposal - add instance' , async function ( ) {
let { sender , instanceFactory , gov , instanceRegistry , tornWhale , tornToken } = await loadFixture ( fixture )
let { sender , instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } =
await loadFixture ( fixture )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( instanceFactory . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
instanceFactory
proposalCreator
. connect ( sender )
. createProposalApprove ( config . COMP , 3000 , [ ethers . utils . parseEther ( '100' ) ] , [ 30 ] ) ,
) . to . changeTokenBalances (
@ -165,7 +178,7 @@ describe('Instance Factory With Registry Tests', () => {
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await instanceFactory . queryFilter ( 'NewGovernanceProposalCreated' )
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
@ -235,7 +248,8 @@ describe('Instance Factory With Registry Tests', () => {
} )
it ( 'Should successfully deploy/propose/execute proposal - add instances' , async function ( ) {
let { sender , instanceFactory , gov , instanceRegistry , tornWhale , tornToken } = await loadFixture ( fixture )
let { sender , instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } =
await loadFixture ( fixture )
const denominations = [
ethers . utils . parseEther ( '1' ) ,
@ -249,17 +263,17 @@ describe('Instance Factory With Registry Tests', () => {
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( instanceFactory . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
instanceFactory . connect ( sender ) . createProposalApprove ( config . COMP , 3000 , denominations , protocolFees ) ,
proposalCreator . connect ( sender ) . createProposalApprove ( config . COMP , 3000 , denominations , protocolFees ) ,
) . to . changeTokenBalances (
tornToken ,
[ sender , gov ] ,
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await instanceFactory . queryFilter ( 'NewGovernanceProposalCreated' )
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
@ -333,7 +347,9 @@ describe('Instance Factory With Registry Tests', () => {
} )
it ( 'Should successfully deploy proposal with permit' , async function ( ) {
let { instanceFactory , gov , instanceRegistry , tornWhale , tornToken } = await loadFixture ( fixture )
let { instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } = await loadFixture (
fixture ,
)
const privateKey = '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3'
const publicKey = '0x' + ethers . utils . computeAddress ( Buffer . from ( privateKey . slice ( 2 ) , 'hex' ) )
@ -358,7 +374,7 @@ describe('Instance Factory With Registry Tests', () => {
const curTimestamp = Math . trunc ( new Date ( ) . getTime ( ) / 1000 )
const args = {
owner : sender ,
spender : instanceFactory . address ,
spender : proposalCreator . address ,
value : config . creationFee ,
nonce : 0 ,
deadline : curTimestamp + 1000 ,
@ -370,7 +386,7 @@ describe('Instance Factory With Registry Tests', () => {
expect ( signer ) . to . equal ( sender . address )
await expect ( ( ) =>
instanceFactory . createProposalPermit (
proposalCreator . createProposalPermit (
config . COMP ,
3000 ,
[ ethers . utils . parseEther ( '100' ) ] ,
@ -387,7 +403,7 @@ describe('Instance Factory With Registry Tests', () => {
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await instanceFactory . queryFilter ( 'NewGovernanceProposalCreated' )
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
@ -403,15 +419,15 @@ describe('Instance Factory With Registry Tests', () => {
} )
it ( 'Should deposit and withdraw into the new instance' , async function ( ) {
let { sender , instanceFactory , gov , tornWhale , tornToken , router , compToken , compWhale } =
let { sender , proposalCreator , gov , tornWhale , tornToken , router , compToken , compWhale } =
await loadFixture ( fixture )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( instanceFactory . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
instanceFactory
proposalCreator
. connect ( sender )
. createProposalApprove ( config . COMP , 3000 , [ ethers . utils . parseEther ( '100' ) ] , [ 30 ] ) ,
) . to . changeTokenBalances (
@ -420,7 +436,7 @@ describe('Instance Factory With Registry Tests', () => {
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await instanceFactory . queryFilter ( 'NewGovernanceProposalCreated' )
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
@ -486,36 +502,382 @@ describe('Instance Factory With Registry Tests', () => {
} )
it ( 'Should not deploy proposal with incorrect Uniswap pool' , async function ( ) {
let { sender , instanceFactory , tornWhale , tornToken } = await loadFixture ( fixture )
let { sender , proposalCreator , tornWhale , tornToken } = await loadFixture ( fixture )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( instanceFactory . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect (
instanceFactory
proposalCreator
. connect ( sender )
. createProposalApprove ( config . COMP , 4000 , [ ethers . utils . parseEther ( '100' ) ] , [ 30 ] ) ,
) . to . be . revertedWith ( 'Uniswap pool is not exist' )
await expect (
instanceFactory
proposalCreator
. connect ( sender )
. createProposalApprove ( config . COMP , 10000 , [ ethers . utils . parseEther ( '100' ) ] , [ 30 ] ) ,
) . to . be . revertedWith ( 'Uniswap pool TWAP slots number is low' )
} )
it ( 'Should not deploy proposal with incorrect protocol fee' , async function ( ) {
let { sender , instanceFactory , tornWhale , tornToken } = await loadFixture ( fixture )
let { sender , proposalCreator , tornWhale , tornToken } = await loadFixture ( fixture )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( instanceFactory . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect (
instanceFactory
proposalCreator
. connect ( sender )
. createProposalApprove ( config . COMP , 3000 , [ ethers . utils . parseEther ( '100' ) ] , [ 10300 ] ) ,
) . to . be . revertedWith ( 'Protocol fee is more than 100%' )
} )
it ( 'Should successfully deploy/propose/execute proposal - add native instance' , async function ( ) {
let { sender , instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } =
await loadFixture ( fixture )
const denomination = ethers . utils . parseEther ( '1.5' )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
proposalCreator . connect ( sender ) . createProposalApprove ( addressZero , 0 , [ denomination ] , [ 30 ] ) ,
) . to . changeTokenBalances (
tornToken ,
[ sender , gov ] ,
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
)
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 ( addressZero )
expect ( await proposal . uniswapPoolSwappingFee ( ) ) . to . be . equal ( 0 )
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 ( denomination )
// propose proposal ---------------------------------------------
let response , id , state
gov = await gov . connect ( tornWhale )
await tornToken . connect ( tornWhale ) . approve ( gov . address , ethers . utils . parseEther ( '26000' ) )
await gov . lockWithApproval ( ethers . utils . parseEther ( '26000' ) )
response = await gov . propose ( proposal . address , 'ETH 1.5 instance proposal' )
id = await gov . latestProposalIds ( tornWhale . address )
state = await gov . state ( id )
const { events } = await response . wait ( )
const args = events . find ( ( { event } ) => event == 'ProposalCreated' ) . args
expect ( args . id ) . to . be . equal ( id )
expect ( args . proposer ) . to . be . equal ( tornWhale . address )
expect ( args . target ) . to . be . equal ( proposal . address )
expect ( args . description ) . to . be . equal ( 'ETH 1.5 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
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . Active )
await minewait (
(
await gov . VOTING _PERIOD ( )
)
. add ( await gov . EXECUTION _DELAY ( ) )
. add ( 96400 )
. toNumber ( ) ,
)
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . AwaitingExecution )
let tx = await gov . execute ( id )
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . Executed )
// check instance initialization --------------------------------
let receipt = await tx . wait ( )
const instanceAddr = '0x' + receipt . events [ 0 ] . topics [ 1 ] . toString ( ) . slice ( - 40 )
const instance = await ethers . getContractAt ( 'ETHTornadoCloneable' , instanceAddr )
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 ( denomination )
const instanceData = await instanceRegistry . instances ( instance . address )
expect ( instanceData . isERC20 ) . to . be . equal ( false )
expect ( instanceData . token ) . to . be . equal ( addressZero )
expect ( instanceData . state ) . to . be . equal ( 1 )
expect ( instanceData . uniswapPoolSwappingFee ) . to . be . equal ( 0 )
expect ( instanceData . protocolFeePercentage ) . to . be . equal ( 30 )
} )
it ( 'Should successfully deploy/propose/execute proposal - add native instances' , async function ( ) {
let { sender , instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } =
await loadFixture ( fixture )
const denominations = [
ethers . utils . parseEther ( '1.5' ) ,
ethers . utils . parseEther ( '10.5' ) ,
ethers . utils . parseEther ( '100.5' ) ,
ethers . utils . parseEther ( '1000.5' ) ,
]
const numInstances = denominations . length
const protocolFees = [ 30 , 30 , 30 , 30 ]
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
proposalCreator . connect ( sender ) . createProposalApprove ( addressZero , 0 , denominations , protocolFees ) ,
) . to . changeTokenBalances (
tornToken ,
[ sender , gov ] ,
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
)
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 ( addressZero )
expect ( await proposal . uniswapPoolSwappingFee ( ) ) . to . be . equal ( 0 )
expect ( await proposal . numInstances ( ) ) . to . be . equal ( numInstances )
for ( let i = 0 ; i < numInstances ; i ++ ) {
expect ( await proposal . protocolFeeByIndex ( i ) ) . to . be . equal ( protocolFees [ i ] )
expect ( await proposal . denominationByIndex ( i ) ) . to . be . equal ( denominations [ i ] )
}
// propose proposal ---------------------------------------------
let response , id , state
gov = await gov . connect ( tornWhale )
await tornToken . connect ( tornWhale ) . approve ( gov . address , ethers . utils . parseEther ( '26000' ) )
await gov . lockWithApproval ( ethers . utils . parseEther ( '26000' ) )
response = await gov . propose ( proposal . address , 'ETH instances proposal' )
id = await gov . latestProposalIds ( tornWhale . address )
state = await gov . state ( id )
const { events } = await response . wait ( )
const args = events . find ( ( { event } ) => event == 'ProposalCreated' ) . args
expect ( args . id ) . to . be . equal ( id )
expect ( args . proposer ) . to . be . equal ( tornWhale . address )
expect ( args . target ) . to . be . equal ( proposal . address )
expect ( args . description ) . to . be . equal ( 'ETH instances 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
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . Active )
await minewait (
(
await gov . VOTING _PERIOD ( )
)
. add ( await gov . EXECUTION _DELAY ( ) )
. add ( 96400 )
. toNumber ( ) ,
)
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . AwaitingExecution )
await gov . execute ( id )
expect ( await gov . state ( id ) ) . to . be . equal ( ProposalState . Executed )
// check instances initialization -------------------------------
logs = await instanceFactory . queryFilter ( 'NewInstanceCloneCreated' )
for ( let i = 0 ; i < numInstances ; i ++ ) {
let instanceAddr = '0x' + logs [ logs . length - numInstances + i ] . topics [ 1 ] . slice ( - 40 )
let instance = await ethers . getContractAt ( 'ETHTornadoCloneable' , instanceAddr )
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 ( denominations [ i ] )
let instanceData = await instanceRegistry . instances ( instance . address )
expect ( instanceData . isERC20 ) . to . be . equal ( false )
expect ( instanceData . token ) . to . be . equal ( addressZero )
expect ( instanceData . state ) . to . be . equal ( 1 )
expect ( instanceData . uniswapPoolSwappingFee ) . to . be . equal ( 0 )
expect ( instanceData . protocolFeePercentage ) . to . be . equal ( protocolFees [ i ] )
}
} )
it ( 'Should successfully deploy proposal with permit for native' , async function ( ) {
let { instanceFactory , proposalCreator , gov , instanceRegistry , tornWhale , tornToken } = await loadFixture (
fixture ,
)
const denomination = ethers . utils . parseEther ( '1.5' )
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 : proposalCreator . 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 ( ( ) =>
proposalCreator . createProposalPermit (
addressZero ,
0 ,
[ denomination ] ,
[ 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 proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
)
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 ( addressZero )
expect ( await proposal . uniswapPoolSwappingFee ( ) ) . to . be . equal ( 0 )
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 ( denomination )
} )
it ( 'Should deposit and withdraw into the new native instance' , async function ( ) {
let { sender , proposalCreator , gov , tornWhale , tornToken , router } = await loadFixture ( fixture )
const denomination = ethers . utils . parseEther ( '1.5' )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect ( ( ) =>
proposalCreator . connect ( sender ) . createProposalApprove ( addressZero , 0 , [ denomination ] , [ 30 ] ) ,
) . to . changeTokenBalances (
tornToken ,
[ sender , gov ] ,
[ BigNumber . from ( 0 ) . sub ( config . creationFee ) , config . creationFee ] ,
)
let logs = await proposalCreator . queryFilter ( 'NewGovernanceProposalCreated' )
const proposal = await ethers . getContractAt (
'AddInstanceProposal' ,
ethers . utils . getAddress ( '0x' + logs [ logs . length - 1 ] . topics [ 1 ] . slice ( - 40 ) ) ,
)
// propose proposal ---------------------------------------------
let id
gov = await gov . connect ( tornWhale )
await tornToken . connect ( tornWhale ) . approve ( gov . address , ethers . utils . parseEther ( '26000' ) )
await gov . lockWithApproval ( ethers . utils . parseEther ( '26000' ) )
await gov . propose ( proposal . address , 'ETH instance proposal' )
id = await gov . latestProposalIds ( tornWhale . address )
// execute proposal ---------------------------------------------
await minewait ( ( await gov . VOTING _DELAY ( ) ) . add ( 1 ) . toNumber ( ) )
await expect ( gov . castVote ( id , true ) ) . to . not . be . reverted
await minewait (
(
await gov . VOTING _PERIOD ( )
)
. add ( await gov . EXECUTION _DELAY ( ) )
. add ( 96400 )
. toNumber ( ) ,
)
let tx = await gov . execute ( id )
let receipt = await tx . wait ( )
const instanceAddr = '0x' + receipt . events [ 0 ] . topics [ 1 ] . toString ( ) . slice ( - 40 )
const instance = await ethers . getContractAt ( 'ETHTornadoCloneable' , instanceAddr )
// check instance work ------------------------------------------
const depo = createDeposit ( {
nullifier : rbigint ( 31 ) ,
secret : rbigint ( 31 ) ,
} )
await expect ( ( ) =>
router . deposit ( instance . address , toHex ( depo . commitment ) , [ ] , { value : denomination } ) ,
) . to . changeEtherBalances ( [ sender , instance ] , [ BigNumber . from ( 0 ) . sub ( denomination ) , denomination ] )
let pevents = await instance . queryFilter ( 'Deposit' )
await initialize ( { merkleTreeHeight : 20 } )
const { proof , args } = await generateProof ( {
deposit : depo ,
recipient : sender . address ,
events : pevents ,
} )
await expect ( ( ) => router . withdraw ( instance . address , proof , ... args ) ) . to . changeEtherBalances (
[ instance , sender ] ,
[ BigNumber . from ( 0 ) . sub ( denomination ) , denomination ] ,
)
} )
it ( 'Should not deploy native currency proposal with incorrect protocol fee' , async function ( ) {
let { sender , proposalCreator , tornWhale , tornToken } = await loadFixture ( fixture )
// deploy proposal ----------------------------------------------
await tornToken . connect ( tornWhale ) . transfer ( sender . address , config . creationFee )
await tornToken . approve ( proposalCreator . address , config . creationFee )
await expect (
proposalCreator
. connect ( sender )
. createProposalApprove ( addressZero , 0 , [ ethers . utils . parseEther ( '1.5' ) ] , [ 10300 ] ) ,
) . to . be . revertedWith ( 'Protocol fee is more than 100%' )
} )
} )