diff --git a/package-lock.json b/package-lock.json index 6c95294694..ece9ea2a5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -654,9 +654,9 @@ } }, "node_modules/@eth-optimism/core-utils": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eth-optimism/core-utils/-/core-utils-0.4.1.tgz", - "integrity": "sha512-aKgAQ9/dfFFLeRy5rF/7v93lvTM7tSYTIdcIadOAFOUG9QnxEH7RpIrWMpwT5S/u4H9iUEyvzTP7RRiZU68pJw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eth-optimism/core-utils/-/core-utils-0.4.2.tgz", + "integrity": "sha512-GQm0zbPfr/FuT0xywcZMEhKzk9VlEOWLRbzbSbBvvHtA6mmCO1oiL/Rr3O3f8DbHXB5JNBOK84tcciCMhJ3BSA==", "dev": true, "dependencies": { "@ethersproject/abstract-provider": "^5.0.9", @@ -4858,9 +4858,9 @@ } }, "node_modules/@uniswap/token-lists": { - "version": "1.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@uniswap/token-lists/-/token-lists-1.0.0-beta.21.tgz", - "integrity": "sha512-IQ1YpWKgXIsfYqym9Nl/uaB1t5Wk70pyqJ2W4FmvQmt3FIQz+pHlzlEl91aYloPrlcZaFluE0Jq7gkfYpIjsBw==", + "version": "1.0.0-beta.24", + "resolved": "https://registry.npmjs.org/@uniswap/token-lists/-/token-lists-1.0.0-beta.24.tgz", + "integrity": "sha512-9IMltV7ITwxnjuK0LYXlUZhYIB8wVAdwx5NAbGjHF9ss+zKL9FTyFfWTFif/EL6PCWvST+2B15ofUwSVZd17RA==", "dev": true, "engines": { "node": ">=10" @@ -12234,7 +12234,9 @@ "resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.2.tgz", "integrity": "sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw==", "bundleDependencies": [ - "keccak" + "keccak", + "node-addon-api", + "node-gyp-build" ], "dev": true, "hasShrinkwrap": true, @@ -30960,9 +30962,9 @@ "dev": true }, "node_modules/uglify-js": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz", - "integrity": "sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw==", + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.6.tgz", + "integrity": "sha512-rRprLwl8RVaS+Qvx3Wh5hPfPBn9++G6xkGlUupya0s5aDmNjI7z3lnRLB3u7sN4OmbB0pWgzhM9BEJyiWAwtAA==", "dev": true, "optional": true, "bin": { @@ -38141,9 +38143,9 @@ } }, "@eth-optimism/core-utils": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eth-optimism/core-utils/-/core-utils-0.4.1.tgz", - "integrity": "sha512-aKgAQ9/dfFFLeRy5rF/7v93lvTM7tSYTIdcIadOAFOUG9QnxEH7RpIrWMpwT5S/u4H9iUEyvzTP7RRiZU68pJw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eth-optimism/core-utils/-/core-utils-0.4.2.tgz", + "integrity": "sha512-GQm0zbPfr/FuT0xywcZMEhKzk9VlEOWLRbzbSbBvvHtA6mmCO1oiL/Rr3O3f8DbHXB5JNBOK84tcciCMhJ3BSA==", "dev": true, "requires": { "@ethersproject/abstract-provider": "^5.0.9", @@ -38454,9 +38456,7 @@ "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz", "integrity": "sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw==", "dev": true, - "requires": { - "ethers": "^5.0.2" - } + "requires": {} }, "commander": { "version": "3.0.2", @@ -41618,9 +41618,9 @@ } }, "@uniswap/token-lists": { - "version": "1.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@uniswap/token-lists/-/token-lists-1.0.0-beta.21.tgz", - "integrity": "sha512-IQ1YpWKgXIsfYqym9Nl/uaB1t5Wk70pyqJ2W4FmvQmt3FIQz+pHlzlEl91aYloPrlcZaFluE0Jq7gkfYpIjsBw==", + "version": "1.0.0-beta.24", + "resolved": "https://registry.npmjs.org/@uniswap/token-lists/-/token-lists-1.0.0-beta.24.tgz", + "integrity": "sha512-9IMltV7ITwxnjuK0LYXlUZhYIB8wVAdwx5NAbGjHF9ss+zKL9FTyFfWTFif/EL6PCWvST+2B15ofUwSVZd17RA==", "dev": true }, "@webassemblyjs/ast": { @@ -62338,9 +62338,9 @@ "dev": true }, "uglify-js": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz", - "integrity": "sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw==", + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.6.tgz", + "integrity": "sha512-rRprLwl8RVaS+Qvx3Wh5hPfPBn9++G6xkGlUupya0s5aDmNjI7z3lnRLB3u7sN4OmbB0pWgzhM9BEJyiWAwtAA==", "dev": true, "optional": true }, diff --git a/test/prod/MultiCollateral.prod.js b/test/prod/MultiCollateral.prod.js index 8e72b083c7..182f326284 100644 --- a/test/prod/MultiCollateral.prod.js +++ b/test/prod/MultiCollateral.prod.js @@ -207,54 +207,75 @@ contract('MultiCollateral (prod tests)', accounts => { .at(await CollateralContract.state()); }); - describe('when opening the loan', () => { - let loan, loanId; - let totalLoansBefore, - longBefore, - totalLongBefore, - shortBefore, - totalShortBefore, - issueFeeRate, - systemDebtBefore; - - before('record current values', async () => { - issueFeeRate = await CollateralContract.issueFeeRate(); - totalLoansBefore = await CollateralManagerState.totalLoans(); - longBefore = await CollateralManager.long(borrowCurrencyBytes); - totalLongBefore = (await CollateralManager.totalLong()).susdValue; - shortBefore = await CollateralManager.short(borrowCurrencyBytes); - totalShortBefore = (await CollateralManager.totalShort()).susdValue; - systemDebtBefore = (await DebtCache.currentDebt()).debt; + describe('when the max debt is not reached', () => { + before('skip if max debt has been reached', async function() { + if (await CollateralManager.exceedsDebtLimit(amountToBorrow, borrowCurrencyBytes)) { + console.log('Skipping, since loan would exceed debt limit'); + + this.skip(); + } }); - before('open the loan', async () => { - if (type === 'CollateralErc20') { - const underlyingToken = await CollateralErc20.underlyingContract(); - const renBTC = await artifacts.require('ERC20').at(underlyingToken); + describe('when opening the loan', () => { + let loan, loanId; + let totalLoansBefore, + longBefore, + totalLongBefore, + shortBefore, + totalShortBefore, + issueFeeRate, + systemDebtBefore; + + before('record current values', async () => { + issueFeeRate = await CollateralContract.issueFeeRate(); + totalLoansBefore = await CollateralManagerState.totalLoans(); + longBefore = await CollateralManager.long(borrowCurrencyBytes); + totalLongBefore = (await CollateralManager.totalLong()).susdValue; + shortBefore = await CollateralManager.short(borrowCurrencyBytes); + totalShortBefore = (await CollateralManager.totalShort()).susdValue; + systemDebtBefore = (await DebtCache.currentDebt()).debt; + }); - let altHolder; - if (network !== 'local') { - const account = knownAccounts[network].find(a => a.name === 'renBTCWallet'); - if (account) { - altHolder = account.address; + before('open the loan', async () => { + if (type === 'CollateralErc20') { + const underlyingToken = await CollateralErc20.underlyingContract(); + const renBTC = await artifacts.require('ERC20').at(underlyingToken); + + let altHolder; + if (network !== 'local') { + const account = knownAccounts[network].find(a => a.name === 'renBTCWallet'); + if (account) { + altHolder = account.address; + } } - } - const renHolder = network === 'local' ? owner : altHolder || owner; - if (!renHolder) { - throw new Error(`No known renBTC holder for network ${network}`); - } + const renHolder = network === 'local' ? owner : altHolder || owner; + if (!renHolder) { + throw new Error(`No known renBTC holder for network ${network}`); + } - // give them more, so they can deposit after opening - const transferAmount = Web3.utils.toBN('10000000000'); + // give them more, so they can deposit after opening + const transferAmount = Web3.utils.toBN('10000000000'); - await renBTC.transfer(user1, transferAmount, { - from: renHolder, - }); + await renBTC.transfer(user1, transferAmount, { + from: renHolder, + }); - await renBTC.approve(CollateralContract.address, toUnit('10000'), { from: user1 }); + await renBTC.approve(CollateralContract.address, toUnit('10000'), { from: user1 }); + + if (!oldContractsOnly) { + tx = await CollateralContract.open( + amountToDeposit, + amountToBorrow, + borrowCurrencyBytes, + { + from: user1, + } + ); + } + } else if (type === 'CollateralShort') { + await SynthsUSD.approve(CollateralContract.address, toUnit('10000'), { from: user1 }); - if (!oldContractsOnly) { tx = await CollateralContract.open( amountToDeposit, amountToBorrow, @@ -263,241 +284,235 @@ contract('MultiCollateral (prod tests)', accounts => { from: user1, } ); - } - } else if (type === 'CollateralShort') { - await SynthsUSD.approve(CollateralContract.address, toUnit('10000'), { from: user1 }); - - tx = await CollateralContract.open( - amountToDeposit, - amountToBorrow, - borrowCurrencyBytes, - { + } else { + tx = await CollateralContract.open(amountToBorrow, borrowCurrencyBytes, { from: user1, - } - ); - } else { - tx = await CollateralContract.open(amountToBorrow, borrowCurrencyBytes, { - from: user1, - value: amountToDeposit, - }); - } + value: amountToDeposit, + }); + } - const event = tx.receipt.logs.find(l => l.event === 'LoanCreated'); - loanId = event.args.id; + const event = tx.receipt.logs.find(l => l.event === 'LoanCreated'); + loanId = event.args.id; - loan = await CollateralStateContract.getLoan(user1, loanId); - }); - - it('emits a LoanCreated event with the expected parameters', async () => { - const event = tx.receipt.logs.find(l => l.event === 'LoanCreated'); + loan = await CollateralStateContract.getLoan(user1, loanId); + }); - assert.equal(event.args.account, user1); - assert.bnEqual(event.args.id, totalLoansBefore.add(Web3.utils.toBN(1))); - assert.bnEqual(event.args.amount, amountToBorrow); - assert.equal(event.args.currency, borrowCurrencyBytes); - assert.bnEqual( - event.args.issuanceFee, - multiplyDecimalRound(amountToBorrow, issueFeeRate) - ); + it('emits a LoanCreated event with the expected parameters', async () => { + const event = tx.receipt.logs.find(l => l.event === 'LoanCreated'); - if (type === 'CollateralErc20') { - // Account for renBTC scaling + assert.equal(event.args.account, user1); + assert.bnEqual(event.args.id, totalLoansBefore.add(Web3.utils.toBN(1))); + assert.bnEqual(event.args.amount, amountToBorrow); + assert.equal(event.args.currency, borrowCurrencyBytes); assert.bnEqual( - event.args.collateral, - amountToDeposit.mul(Web3.utils.toBN('10000000000')) + event.args.issuanceFee, + multiplyDecimalRound(amountToBorrow, issueFeeRate) ); - } else { - assert.bnEqual(event.args.collateral, amountToDeposit); - } - }); - - it('updates the managers short/long values', async () => { - if (type === 'CollateralShort') { - const shortAfter = await CollateralManager.short(borrowCurrencyBytes); - const totalShortAfter = (await CollateralManager.totalShort()).susdValue; - - assert.bnGt(shortAfter, shortBefore); - assert.bnGt(totalShortAfter, totalShortBefore); - } else { - const longAfter = await CollateralManager.long(borrowCurrencyBytes); - const totalLongAfter = (await CollateralManager.totalLong()).susdValue; - assert.bnEqual(longAfter, longBefore.add(amountToBorrow)); - assert.bnEqual(totalLongAfter, totalLongBefore.add(amountToBorrow)); - } - }); + if (type === 'CollateralErc20') { + // Account for renBTC scaling + assert.bnEqual( + event.args.collateral, + amountToDeposit.mul(Web3.utils.toBN('10000000000')) + ); + } else { + assert.bnEqual(event.args.collateral, amountToDeposit); + } + }); - it('does not increment the system debt', async () => { - const systemDebtAfter = (await DebtCache.currentDebt()).debt; + it('updates the managers short/long values', async () => { + if (type === 'CollateralShort') { + const shortAfter = await CollateralManager.short(borrowCurrencyBytes); + const totalShortAfter = (await CollateralManager.totalShort()).susdValue; - assert.bnEqual(systemDebtAfter, systemDebtBefore); - }); + assert.bnGt(shortAfter, shortBefore); + assert.bnGt(totalShortAfter, totalShortBefore); + } else { + const longAfter = await CollateralManager.long(borrowCurrencyBytes); + const totalLongAfter = (await CollateralManager.totalLong()).susdValue; - describe('when depositing more collateral', () => { - let cratioBefore; + assert.bnEqual(longAfter, longBefore.add(amountToBorrow)); + assert.bnEqual(totalLongAfter, totalLongBefore.add(amountToBorrow)); + } + }); - before('skip waiting period', async () => { - const period = await CollateralContract.interactionDelay(); + it('does not increment the system debt', async () => { + const systemDebtAfter = (await DebtCache.currentDebt()).debt; - await fastForward(period.toString()); + assert.bnEqual(systemDebtAfter, systemDebtBefore); }); - before('record current values', async () => { - loan = await CollateralStateContract.getLoan(user1, loanId); - cratioBefore = await CollateralContract.collateralRatio(loan); - }); + describe('when depositing more collateral', () => { + let cratioBefore; - before('deposit', async () => { - if (type === 'CollateralErc20') { - tx = await CollateralContract.deposit(user1, loanId, Web3.utils.toBN('1000000000'), { - from: user1, - }); - } else if (type === 'CollateralShort') { - tx = await CollateralContract.deposit(user1, loanId, toUnit('200'), { - from: user1, - }); - } else { - tx = await CollateralContract.deposit(user1, loanId, { - from: user1, - value: toUnit('1'), - }); - } + before('skip waiting period', async () => { + const period = await CollateralContract.interactionDelay(); - loan = await CollateralStateContract.getLoan(user1, loanId); - }); + await fastForward(period.toString()); + }); - it('incrementes the cratio', async () => { - const cratioAfter = await CollateralContract.collateralRatio(loan); + before('record current values', async () => { + loan = await CollateralStateContract.getLoan(user1, loanId); + cratioBefore = await CollateralContract.collateralRatio(loan); + }); - assert.bnGt(cratioAfter, cratioBefore); - }); - }); + before('deposit', async () => { + if (type === 'CollateralErc20') { + tx = await CollateralContract.deposit( + user1, + loanId, + Web3.utils.toBN('1000000000'), + { + from: user1, + } + ); + } else if (type === 'CollateralShort') { + tx = await CollateralContract.deposit(user1, loanId, toUnit('200'), { + from: user1, + }); + } else { + tx = await CollateralContract.deposit(user1, loanId, { + from: user1, + value: toUnit('1'), + }); + } - describe('when removing collateral', () => { - let cratioBefore; + loan = await CollateralStateContract.getLoan(user1, loanId); + }); - before('skip waiting period', async () => { - const period = await CollateralContract.interactionDelay(); + it('incrementes the cratio', async () => { + const cratioAfter = await CollateralContract.collateralRatio(loan); - await fastForward(period.toString()); + assert.bnGt(cratioAfter, cratioBefore); + }); }); - before('record current values', async () => { - loan = await CollateralStateContract.getLoan(user1, loanId); - cratioBefore = await CollateralContract.collateralRatio(loan); - }); + describe('when removing collateral', () => { + let cratioBefore; - before('withdraw', async () => { - tx = await CollateralContract.withdraw(loanId, Web3.utils.toBN('100'), { - from: user1, - }); + before('skip waiting period', async () => { + const period = await CollateralContract.interactionDelay(); - loan = await CollateralStateContract.getLoan(user1, loanId); - }); + await fastForward(period.toString()); + }); - it('decrementes the cratio', async () => { - const cratioAfter = await CollateralContract.collateralRatio(loan); + before('record current values', async () => { + loan = await CollateralStateContract.getLoan(user1, loanId); + cratioBefore = await CollateralContract.collateralRatio(loan); + }); - assert.bnLt(cratioAfter, cratioBefore); - }); - }); + before('withdraw', async () => { + tx = await CollateralContract.withdraw(loanId, Web3.utils.toBN('100'), { + from: user1, + }); - describe('when repaying the loan', () => { - before('skip waiting period', async () => { - const period = await CollateralContract.interactionDelay(); + loan = await CollateralStateContract.getLoan(user1, loanId); + }); - await fastForward(period.toString()); - }); + it('decrementes the cratio', async () => { + const cratioAfter = await CollateralContract.collateralRatio(loan); - before('repay some debt', async () => { - tx = await CollateralContract.repay(user1, loanId, amountToRepay, { - from: user1, + assert.bnLt(cratioAfter, cratioBefore); }); }); - describe('when closing the loan', () => { + describe('when repaying the loan', () => { before('skip waiting period', async () => { const period = await CollateralContract.interactionDelay(); await fastForward(period.toString()); }); - before('close the loan', async () => { - tx = await CollateralContract.close(loanId, { + before('repay some debt', async () => { + tx = await CollateralContract.repay(user1, loanId, amountToRepay, { from: user1, }); - - loan = await CollateralStateContract.getLoan(user1, loanId); }); - it('shows that the loan amount is zero', async () => { - assert.bnEqual(loan.amount, '0'); + describe('when closing the loan', () => { + before('skip waiting period', async () => { + const period = await CollateralContract.interactionDelay(); + + await fastForward(period.toString()); + }); + + before('close the loan', async () => { + tx = await CollateralContract.close(loanId, { + from: user1, + }); + + loan = await CollateralStateContract.getLoan(user1, loanId); + }); + + it('shows that the loan amount is zero', async () => { + assert.bnEqual(loan.amount, '0'); + }); }); }); }); - }); - }); - } - describe('old contracts still work', () => { - it('has the old and new contracts in the manager', async () => { - if (network === 'mainnet' && !oldContractsOnly) { - const result = await CollateralManager.hasAllCollaterals([ - oldEthAddress, - oldRenAddress, - oldShortAddress, - CollateralEth.address, - CollateralErc20.address, - CollateralShort.address, - ]); - assert.isTrue(result); - } - }); + describe('old contracts still work', () => { + it('has the old and new contracts in the manager', async () => { + if (network === 'mainnet' && !oldContractsOnly) { + const result = await CollateralManager.hasAllCollaterals([ + oldEthAddress, + oldRenAddress, + oldShortAddress, + CollateralEth.address, + CollateralErc20.address, + CollateralShort.address, + ]); + assert.isTrue(result); + } + }); - it('interacting with a loan on the old ETH contract works', async () => { - if (network === 'mainnet') { - const oldEthContract = await artifacts.require('CollateralEth').at(oldEthAddress); - const period = await oldEthContract.interactionDelay(); - // First loan was opened by SNX test account. - const id = 1; - const repayAmount = toUnit(100); - let tx = await oldEthContract.repay(loansAccount, id, repayAmount, { - from: loansAccount, - }); + it('interacting with a loan on the old ETH contract works', async () => { + if (network === 'mainnet') { + const oldEthContract = await artifacts.require('CollateralEth').at(oldEthAddress); + const period = await oldEthContract.interactionDelay(); + // First loan was opened by SNX test account. + const id = 1; + const repayAmount = toUnit(100); + let tx = await oldEthContract.repay(loansAccount, id, repayAmount, { + from: loansAccount, + }); - let event = tx.receipt.logs.find(l => l.event === 'LoanRepaymentMade'); + let event = tx.receipt.logs.find(l => l.event === 'LoanRepaymentMade'); - assert.equal(event.args.account, loansAccount); - assert.equal(event.args.repayer, loansAccount); - assert.equal(event.args.id, id); - assert.bnEqual(event.args.amountRepaid, repayAmount); + assert.equal(event.args.account, loansAccount); + assert.equal(event.args.repayer, loansAccount); + assert.equal(event.args.id, id); + assert.bnEqual(event.args.amountRepaid, repayAmount); - const withdrawAmount = toUnit(0.5); - const amountRemaining = toUnit(1.5); + const withdrawAmount = toUnit(0.5); + const amountRemaining = toUnit(1.5); - await fastForward(period.toString()); + await fastForward(period.toString()); - tx = await oldEthContract.withdraw(id, withdrawAmount, { - from: loansAccount, - }); + tx = await oldEthContract.withdraw(id, withdrawAmount, { + from: loansAccount, + }); - event = tx.receipt.logs.find(l => l.event === 'CollateralWithdrawn'); + event = tx.receipt.logs.find(l => l.event === 'CollateralWithdrawn'); - assert.equal(event.args.account, loansAccount); - assert.bnEqual(event.args.amountWithdrawn, withdrawAmount); - assert.bnEqual(event.args.collateralAfter, amountRemaining); + assert.equal(event.args.account, loansAccount); + assert.bnEqual(event.args.amountWithdrawn, withdrawAmount); + assert.bnEqual(event.args.collateralAfter, amountRemaining); - await fastForward(period.toString()); + await fastForward(period.toString()); - tx = await oldEthContract.close(id, { - from: loansAccount, - }); + tx = await oldEthContract.close(id, { + from: loansAccount, + }); - event = tx.receipt.logs.find(l => l.event === 'LoanClosed'); + event = tx.receipt.logs.find(l => l.event === 'LoanClosed'); - assert.equal(event.args.account, loansAccount); - assert.equal(event.args.id, id); - } + assert.equal(event.args.account, loansAccount); + assert.equal(event.args.id, id); + } + }); + }); + }); }); - }); + } });