diff --git a/contracts/FundingVault.sol b/contracts/FundingVault.sol index 290abbfa..12949247 100644 --- a/contracts/FundingVault.sol +++ b/contracts/FundingVault.sol @@ -13,7 +13,7 @@ contract FundingVault { using SafeERC20 for IERC20; address private immutable _loan; - IERC20 private immutable _asset; + IERC20 public immutable asset; /** * @dev Modifier restricting access to pool @@ -26,11 +26,11 @@ contract FundingVault { /** * @dev Constructor for the vault * @param loan address of loan - * @param asset asset held by vault + * @param asset_ asset held by vault */ - constructor(address loan, address asset) { + constructor(address loan, address asset_) { _loan = loan; - _asset = IERC20(asset); + asset = IERC20(asset_); } /** @@ -38,6 +38,6 @@ contract FundingVault { */ function withdraw(uint256 amount, address receiver) external onlyLoan { require(receiver != address(0), "FundingVault: 0 address"); - _asset.safeTransfer(receiver, amount); + asset.safeTransfer(receiver, amount); } } diff --git a/contracts/Pool.sol b/contracts/Pool.sol index e24aa15f..675edc47 100644 --- a/contracts/Pool.sol +++ b/contracts/Pool.sol @@ -221,7 +221,11 @@ contract Pool is IPool, ERC20 { /** * @dev Called by the pool manager, this transfers liquidity from the pool to a given loan. */ - function fundLoan(address addr) external onlyManager { + function fundLoan(address addr) + external + onlyManager + atState(IPoolLifeCycleState.Active) + { ILoan loan = ILoan(addr); _liquidityAsset.safeApprove(address(loan), loan.principal()); diff --git a/contracts/interfaces/ILoan.sol b/contracts/interfaces/ILoan.sol index 3ec929b6..3e863795 100644 --- a/contracts/interfaces/ILoan.sol +++ b/contracts/interfaces/ILoan.sol @@ -26,6 +26,16 @@ struct ILoanNonFungibleCollateral { } interface ILoan { + /** + * @dev Emitted when loan is funded. + */ + event LoanFunded(address asset, uint256 amount); + + /** + * @dev Emitted when the loan is drawn down. + */ + event LoanDrawnDown(address asset, uint256 amount); + /** * @dev Emitted when a Loan's lifecycle state transitions */ diff --git a/contracts/libraries/LoanLib.sol b/contracts/libraries/LoanLib.sol index 4b829a2b..71400e7a 100644 --- a/contracts/libraries/LoanLib.sol +++ b/contracts/libraries/LoanLib.sol @@ -15,6 +15,16 @@ library LoanLib { using SafeERC20 for IERC20; using SafeMath for uint256; + /** + * @dev Emitted when loan is funded. + */ + event LoanFunded(address asset, uint256 amount); + + /** + * @dev Emitted when the loan is drawn down. + */ + event LoanDrawnDown(address asset, uint256 amount); + /** * @dev Emitted when collateral is posted to the loan. */ @@ -168,6 +178,7 @@ library LoanLib { address(fundingVault), amount ); + emit LoanFunded(liquidityAsset, amount); return ILoanLifeCycleState.Funded; } @@ -180,5 +191,6 @@ library LoanLib { address receiver ) public { fundingVault.withdraw(amount, receiver); + emit LoanDrawnDown(address(fundingVault.asset()), amount); } } diff --git a/test/Loan.test.ts b/test/Loan.test.ts index 082328f4..be529627 100644 --- a/test/Loan.test.ts +++ b/test/Loan.test.ts @@ -366,7 +366,8 @@ describe("Loan", () => { it("transitions Loan to Funded state", async () => { const fixture = await loadFixture(deployFixture); let { loan } = fixture; - const { borrower, collateralAsset, pool, poolManager } = fixture; + const { borrower, collateralAsset, liquidityAsset, pool, poolManager } = + fixture; // Connect as borrower loan = loan.connect(borrower); @@ -376,8 +377,22 @@ describe("Loan", () => { await expect(loan.postFungibleCollateral(collateralAsset.address, 100)) .not.to.be.reverted; expect(await loan.state()).to.equal(1); - await expect(pool.connect(poolManager).fundLoan(loan.address)).not.to.be - .reverted; + const fundTx = pool.connect(poolManager).fundLoan(loan.address); + await expect(fundTx).not.to.be.reverted; + await expect(fundTx) + .to.emit(loan, "LoanFunded") + .withArgs(loan.liquidityAsset, 500_000); + await expect(fundTx).to.changeTokenBalance( + liquidityAsset, + await loan.fundingVault(), + 500_000 + ); + await expect(fundTx).to.changeTokenBalance( + liquidityAsset, + pool, + -500_000 + ); + expect(await loan.state()).to.equal(4); }); @@ -442,6 +457,14 @@ describe("Loan", () => { borrower.address, 500_000 ); + await expect(drawDownTx).to.changeTokenBalance( + liquidityAsset, + await loan.fundingVault(), + -500_000 + ); + await expect(drawDownTx) + .to.emit(loan, "LoanDrawnDown") + .withArgs(loan.liquidityAsset, 500_000); // Try again const drawDownTx2 = loan.connect(borrower).drawdown();