import "module-alias/register" ; import { BigNumber } from "ethers" ; import { Address } from "@utils/types" ; import { Account } from "@utils/test/types" ; import { ADDRESS_ZERO , ZERO } from "@utils/constants" ; import { AirdropModule , CurveStakingAdapter , SetToken , StakingModule , StandardTokenMock } from "@utils/contracts" ; import DeployHelper from "@utils/deploys" ; import { ether , } from "@utils/index" ; import { getAccounts , getWaffleExpect , getSystemFixture , getCurveFixture , addSnapshotBeforeRestoreAfterEach , } from "@utils/test/index" ; import { CurveFixture , SystemFixture } from "@utils/fixtures" ; import { LiquidityGauge } from "@utils/contracts/curve" ; const expect = getWaffleExpect ( ) ; describe ( "curveStakingModule" , ( ) => { let owner ; let deployer ; let setup ; let stakingModule ; let curveStaking ; let airdropModule ; let curveSetup ; let usdt ; let susd ; let gauge ; const curveStakingAdapterIntegrationName = "CURVE_STAKE" ; before ( async ( ) => { [ owner , ] = await getAccounts ( ) ; deployer = new DeployHelper ( owner . wallet ) ; setup = getSystemFixture ( owner . address ) ; await setup . initialize ( ) ; await setup . controller . addModule ( owner . address ) ; usdt = await deployer . mocks . deployTokenMock ( owner . address , ether ( 10000 ) , 6 ) ; susd = await deployer . mocks . deployTokenMock ( owner . address , ether ( 10000 ) , 18 ) ; curveSetup = getCurveFixture ( owner . address ) ; await curveSetup . initializePool ( [ setup . dai . address , setup . usdc . address , usdt . address , susd . address ] ) ; await curveSetup . initializeDAO ( ) ; gauge = await curveSetup . initializeGauge ( curveSetup . poolToken . address ) ; stakingModule = await deployer . modules . deployStakingModule ( setup . controller . address ) ; await setup . controller . addModule ( stakingModule . address ) ; curveStaking = await deployer . adapters . deployCurveStakingAdapter ( curveSetup . gaugeController . address ) ; await setup . integrationRegistry . addIntegration ( stakingModule . address , curveStakingAdapterIntegrationName , curveStaking . address ) ; airdropModule = await deployer . modules . deployAirdropModule ( setup . controller . address ) ; await setup . controller . addModule ( airdropModule . address ) ; const subject18DecimalAmount = ether ( 10 ) ; const subject6DecimalAmount = 10000000 ; await setup . dai . approve ( curveSetup . deposit . address , subject18DecimalAmount ) ; await setup . usdc . approve ( curveSetup . deposit . address , subject6DecimalAmount ) ; await usdt . approve ( curveSetup . deposit . address , subject6DecimalAmount ) ; await susd . approve ( curveSetup . deposit . address , subject18DecimalAmount ) ; await curveSetup . deposit . add_liquidity ( [ subject18DecimalAmount , subject6DecimalAmount , subject6DecimalAmount , subject18DecimalAmount ] , 0 , { gasLimit : 5000000 , } ) ; } ) ; addSnapshotBeforeRestoreAfterEach ( ) ; context ( "when a SetToken has been deployed and issued" , async ( ) => { let setToken ; let setTokensIssued ; before ( async ( ) => { setToken = await setup . createSetToken ( [ setup . dai . address ] , [ ether ( 1 ) ] , [ setup . issuanceModule . address , stakingModule . address , airdropModule . address , owner . address ] ) ; await setToken . initializeModule ( ) ; await setup . issuanceModule . initialize ( setToken . address , ADDRESS_ZERO ) ; await stakingModule . initialize ( setToken . address ) ; await airdropModule . initialize ( setToken . address , { airdrops : [ curveSetup . poolToken . address ] , airdropFee : ZERO , anyoneAbsorb : true , feeRecipient : owner . address , } ) ; setTokensIssued = ether ( 10 ) ; const underlyingRequired = setTokensIssued ; await setup . dai . approve ( setup . controller . address , underlyingRequired ) ; await setup . issuanceModule . issue ( setToken . address , setTokensIssued , owner . address ) ; } ) ; describe ( "when a SetToken provided liquidity" , async ( ) => { let subjectStakingContract ; let subjectSetToken ; let subjectComponent ; beforeEach ( async ( ) => { subjectSetToken = setToken . address ; subjectStakingContract = gauge . address ; subjectComponent = curveSetup . poolToken . address ; const amount = ether ( 10 ) ; const approveDepositCallData = setup . dai . interface . encodeFunctionData ( "approve" , [ curveSetup . deposit . address , amount ] ) ; await setToken . invoke ( setup . dai . address , ZERO , approveDepositCallData ) ; const addLiquidityCallData = curveSetup . deposit . interface . encodeFunctionData ( "add_liquidity" , [ [ amount , 0 , 0 , 0 ] , 0 ] ) ; await setToken . invoke ( curveSetup . deposit . address , ZERO , addLiquidityCallData , { gasLimit : 5000000 , } ) ; await airdropModule . absorb ( subjectSetToken , subjectComponent ) ; } ) ; async function subject ( ) { return stakingModule . stake ( subjectSetToken , subjectStakingContract , subjectComponent , curveStakingAdapterIntegrationName , ether ( .5 ) , { gasLimit : 5000000 , } ) ; } it ( "should be able to stake lp tokens to gauge" , async ( ) => { const prevBalance = await curveSetup . poolToken . balanceOf ( subjectSetToken ) ; await subject ( ) ; const balance = await curveSetup . poolToken . balanceOf ( subjectSetToken ) ; expect ( balance ) . to . lt ( prevBalance ) ; } ) ; describe ( "when a SetToken staked lp tokens" , async ( ) => { beforeEach ( async ( ) => { await stakingModule . stake ( subjectSetToken , subjectStakingContract , subjectComponent , curveStakingAdapterIntegrationName , ether ( .5 ) , { gasLimit : 5000000 , } ) ; } ) ; async function subject ( ) { await stakingModule . unstake ( subjectSetToken , subjectStakingContract , subjectComponent , curveStakingAdapterIntegrationName , ether ( .5 ) , { gasLimit : 5000000 , } ) ; } it ( "should be able to withdraw" , async ( ) => { const prevBalance = await curveSetup . poolToken . balanceOf ( subjectSetToken ) ; await subject ( ) ; const balance = await curveSetup . poolToken . balanceOf ( subjectSetToken ) ; expect ( balance ) . to . gt ( prevBalance ) ; } ) ; } ) ; } ) ; } ) ; } ) ;