Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VAL-105 Add withdraw / redeem methods and tests to PermissionedPool #111

Merged
merged 5 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions contracts/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ contract Pool is IPool, ERC20 {
_;
}

/**
* @dev Modifier that can be overriden by derived classes to enforce
* access control.
*/
modifier onlyPermittedLender() virtual {
_;
}

/**
* @dev Constructor for Pool
* @param liquidityAsset asset held by the poo
Expand Down Expand Up @@ -648,6 +656,7 @@ contract Pool is IPool, ERC20 {
virtual
override
atState(IPoolLifeCycleState.Active)
onlyPermittedLender
onlyCrankedPool
returns (uint256 shares)
{
Expand Down Expand Up @@ -705,6 +714,7 @@ contract Pool is IPool, ERC20 {
virtual
override
atState(IPoolLifeCycleState.Active)
onlyPermittedLender
onlyCrankedPool
returns (uint256 assets)
{
Expand Down Expand Up @@ -755,7 +765,13 @@ contract Pool is IPool, ERC20 {
uint256 assets,
address receiver,
address owner
) external virtual onlyCrankedPool returns (uint256 shares) {
)
public
virtual
onlyPermittedLender
onlyCrankedPool
returns (uint256 shares)
{
require(receiver == owner, "Pool: Withdrawal to unrelated address");
require(receiver == msg.sender, "Pool: Must transfer to msg.sender");
require(assets > 0, "Pool: 0 withdraw not allowed");
Expand Down Expand Up @@ -803,7 +819,13 @@ contract Pool is IPool, ERC20 {
uint256 shares,
address receiver,
address owner
) external virtual onlyCrankedPool returns (uint256 assets) {
)
public
virtual
onlyPermittedLender
onlyCrankedPool
returns (uint256 assets)
{
require(receiver == owner, "Pool: Withdrawal to unrelated address");
require(receiver == msg.sender, "Pool: Must transfer to msg.sender");
require(shares > 0, "Pool: 0 redeem not allowed");
Expand Down
75 changes: 7 additions & 68 deletions contracts/permissioned/PermissionedPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,14 @@ contract PermissionedPool is Pool {
/**
* @dev a modifier to only allow valid lenders to perform an action
*/
modifier onlyValidLender() {
modifier onlyPermittedLender() override {
require(
poolAccessControl.isValidParticipant(msg.sender),
"caller is not a valid lender"
);
_;
}

/**
* @dev a modifier to only allow valid lenders to perform an action
*/
modifier onlyValidReceiver(address receiver) {
require(
poolAccessControl.isValidParticipant(receiver),
"receiver is not a valid lender"
);
_;
}

/**
* @dev The constructor for the PermissionedPool contract. It calls the
* constructor of the Pool contract and then creates a new instance of the
Expand Down Expand Up @@ -85,17 +74,16 @@ contract PermissionedPool is Pool {

/**
* @inheritdoc Pool
* @dev Since Pool does not enforce that msg.sender == receiver, we only
* check the receiver here.
*/
function maxDeposit(address receiver)
public
view
override
returns (uint256)
{
if (
!poolAccessControl.isValidParticipant(msg.sender) ||
!poolAccessControl.isValidParticipant(receiver)
) {
if (!poolAccessControl.isValidParticipant(receiver)) {
return 0;
}

Expand All @@ -104,63 +92,14 @@ contract PermissionedPool is Pool {

/**
* @inheritdoc Pool
*/
function deposit(uint256 assets, address receiver)
public
override
onlyValidLender
onlyValidReceiver(receiver)
returns (uint256 shares)
{
return super.deposit(assets, receiver);
}

/**
* @inheritdoc Pool
* @dev Since Pool does not enforce that msg.sender == receiver, we only
* check the receiver here.
*/
function maxMint(address receiver) public view override returns (uint256) {
if (
!poolAccessControl.isValidParticipant(msg.sender) ||
!poolAccessControl.isValidParticipant(receiver)
) {
if (!poolAccessControl.isValidParticipant(receiver)) {
return 0;
}

return super.maxMint(receiver);
}

/**
* @inheritdoc Pool
*/
function mint(uint256 shares, address receiver)
public
override
onlyValidLender
onlyValidReceiver(receiver)
returns (uint256)
{
return super.mint(shares, receiver);
}

/**
* @inheritdoc Pool
*/
function withdraw(
uint256, /* assets */
address, /* receiver */
address /* owner */
) external override onlyValidLender returns (uint256 shares) {
return 0;
}

/**
* @inheritdoc Pool
*/
function redeem(
uint256, /* shares */
address, /* receiver */
address /* owner */
) external override onlyValidLender returns (uint256 assets) {
return 0;
}
}
89 changes: 88 additions & 1 deletion test/Pool.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { deployPool, depositToPool, activatePool } from "./support/pool";
import {
deployPool,
depositToPool,
activatePool,
DEFAULT_POOL_SETTINGS
} from "./support/pool";
import { deployLoan, collateralizeLoan, fundLoan } from "./support/loan";

describe("Pool", () => {
Expand Down Expand Up @@ -67,6 +72,47 @@ describe("Pool", () => {
return { pool, otherAccount, loan, borrower, liquidityAsset };
}

describe("maxDeposit()", async () => {
it("returns 0 when pool is still initialized", async () => {
const { pool, otherAccount } = await loadFixture(loadPoolFixture);
expect(await pool.maxDeposit(otherAccount.address)).to.equal(0);
});

it("returns the full pool capacity when the pool is activated", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);

expect(await pool.maxDeposit(otherAccount.address)).to.equal(
DEFAULT_POOL_SETTINGS.maxCapacity
);
});

it("returns the full pool capacity less totalAvailableAssets", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);
const depositAmt = 10;
await depositToPool(pool, otherAccount, liquidityAsset, depositAmt);

expect(await pool.maxDeposit(otherAccount.address)).to.equal(
DEFAULT_POOL_SETTINGS.maxCapacity - depositAmt
);
});

it("returns 0 when pool is closed ", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);
const { endDate } = await pool.settings();
await time.increaseTo(endDate);
expect(await pool.maxDeposit(otherAccount.address)).to.equal(0);
});
});

describe("deposit()", async () => {
it("deposit cannot be called if pool is initialized", async () => {
const { pool, otherAccount } = await loadFixture(loadPoolFixture);
Expand Down Expand Up @@ -163,6 +209,47 @@ describe("Pool", () => {
});
});

describe("maxMint()", async () => {
it("returns 0 when pool is still initialized", async () => {
const { pool, otherAccount } = await loadFixture(loadPoolFixture);
expect(await pool.maxMint(otherAccount.address)).to.equal(0);
});

it("returns the full pool capacity when the pool is activated", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);

expect(await pool.maxMint(otherAccount.address)).to.equal(
DEFAULT_POOL_SETTINGS.maxCapacity
);
});

it("returns the full pool capacity less totalAvailableAssets", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);
const depositAmt = 10;
await depositToPool(pool, otherAccount, liquidityAsset, depositAmt);

expect(await pool.maxMint(otherAccount.address)).to.equal(
DEFAULT_POOL_SETTINGS.maxCapacity - depositAmt
);
});

it("returns 0 when pool is closed ", async () => {
const { pool, poolAdmin, otherAccount, liquidityAsset } =
await loadFixture(loadPoolFixture);

await activatePool(pool, poolAdmin, liquidityAsset);
const { endDate } = await pool.settings();
await time.increaseTo(endDate);
expect(await pool.maxMint(otherAccount.address)).to.equal(0);
});
});

describe("mint()", async () => {
it("mint cannot be called if pool is initialized", async () => {
const { pool, otherAccount } = await loadFixture(loadPoolFixture);
Expand Down
Loading