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

Extend fork tests + add locked GEM logic #2

Merged
merged 9 commits into from
Mar 4, 2024
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
35 changes: 30 additions & 5 deletions src/Conduit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface ERC20Like {
function balanceOf(address user) external returns (uint256 amount);
function mint(address user, uint256 amount) external;
function burn(address user, uint256 amount) external;
function totalSupply() external returns (uint256);
}

interface OutputConduitLike {
Expand Down Expand Up @@ -70,6 +71,8 @@ contract Conduit {
mapping(address => uint256) public can;
mapping(address => uint256) public may;

bool public unlockActive = false; // unlocks gem for mkr repayment

/// -- Events --
event Rely(address indexed usr);
event Deny(address indexed usr);
Expand Down Expand Up @@ -189,7 +192,8 @@ contract Conduit {
outputConduit.push();

// Mint deposit tokens
uint256 amount = gem.balanceOf(address(this));
uint256 amount = unlockedGem(); // only gem that is not used as collateral for already deposited depositAssets
// can be used to deposit
depositAsset.mint(address(this), amount);

// Deposit in pool
Expand All @@ -206,26 +210,29 @@ contract Conduit {
/// @notice Burn deposit tokens and withdraw gem
function withdrawFromPool() public onlyMate {
require(withdrawal != address(0), "AndromedaPaymentConduit/withdrawal-is-zero");
require(depositAsset.balanceOf(address(this)) > 0, "AndromedaPaymentConduit/nothing-to-withdraw");

uint256 amount = depositAsset.balanceOf(address(this));
depositAsset.burn(address(this), amount);

gem.transferFrom(address(this), withdrawal, amount);
gem.transfer(withdrawal, amount); // use transfer here: transferFrom not working for USDC
}

/// -- On-ramp and Repay --
/// @notice Submit redemption request for LTF tokens
function requestRedeem(uint256 amount) public onlyMate {
claimDeposit();
// claim tranchetokens from previously fulfilled orders, in case they haven't been claimed yet
try pool.deposit(pool.maxDeposit(address(this)), address(this)) {} catch {} // can not call contract function

pool.requestRedeem(amount, address(this), address(this), "");
}

/// @notice Lock deposit tokens in pool
function depositIntoPool() public onlyMate {
require(depositRecipient != "", "AndromedaPaymentConduit/deposit-recipient-is-zero");

uint256 amount = gem.balanceOf(address(this));
uint256 amount = unlockedGem();
depositAsset.mint(address(this), amount);
depositAsset.approve(address(poolManager), amount);
poolManager.transfer(address(depositAsset), depositRecipient, _toUint128(amount));
}

Expand All @@ -239,16 +246,26 @@ contract Conduit {

/// @notice Send gem as interest to jar
function repayToJar(uint256 amount) public onlyMate {
require(amount <= unlockedGem() || unlockActive, "AndromedaPaymentConduit/no-unlocked-gem-left");
gem.transfer(address(jarConduit), amount);
jarConduit.push();
}

/// @notice Send gem as principal to urn
function repayToUrn(uint256 amount) public onlyMate {
require(amount <= unlockedGem() || unlockActive, "AndromedaPaymentConduit/no-unlocked-gem-left");
gem.transfer(address(urnConduit), amount);
urnConduit.push();
}

/// @notice Unlocked gem = gem that is not used as collateral for depositAssets
function unlockedGem() public returns (uint256) {
if (depositAsset.totalSupply() >= gem.balanceOf(address(this))) {
return 0;
}
return gem.balanceOf(address(this)) - depositAsset.totalSupply();
}

/// -- Fail-safes --
function authMint(uint256 amount) public onlyMate {
depositAsset.mint(address(this), amount);
Expand All @@ -258,6 +275,14 @@ contract Conduit {
depositAsset.burn(address(this), amount);
}

function unlock() public onlyMate {
unlockActive = true;
}

function lock() public onlyMate {
unlockActive = false;
}

/// -- Helpers --
function _toUint128(uint256 _value) internal pure returns (uint128 value) {
if (_value > type(uint128).max) {
Expand Down
25 changes: 25 additions & 0 deletions test/Conduit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ contract ConduitTest is Test {

function testWithdrawFromPool(address notMate, uint256 gemAmount) public {
vm.assume(mate != notMate);
vm.assume(gemAmount > 0);

outputConduit.setPush(gemAmount);
pool.setReturn("maxDeposit", gemAmount);
Expand Down Expand Up @@ -189,6 +190,7 @@ contract ConduitTest is Test {

function testRequestRedeem(address notMate, uint256 gemAmount) public {
vm.assume(mate != notMate);
vm.assume(gemAmount > 0);

outputConduit.setPush(gemAmount);
pool.setReturn("maxDeposit", gemAmount);
Expand Down Expand Up @@ -333,6 +335,29 @@ contract ConduitTest is Test {
assertEq(depositAsset.balanceOf(address(conduit)), amount);
}

function testAuthLockUnlock(address notMate, uint256 amount) public {
vm.assume(mate != notMate);
assert(conduit.unlockActive() == false);

vm.expectRevert(bytes("AndromedaPaymentConduit/not-mate"));
vm.prank(notMate);
conduit.unlock();
assert(conduit.unlockActive() == false);

vm.prank(mate);
conduit.unlock();
assert(conduit.unlockActive() == true);

vm.expectRevert(bytes("AndromedaPaymentConduit/not-mate"));
vm.prank(notMate);
conduit.lock();
assert(conduit.unlockActive() == true);

vm.prank(mate);
conduit.lock();
assert(conduit.unlockActive() == false);
}

function testAuthBurn(address notMate, uint256 mintAmount, uint256 burnAmount) public {
vm.assume(mate != notMate);
burnAmount = bound(burnAmount, 0, mintAmount);
Expand Down
Loading
Loading