Skip to content

Commit

Permalink
PositionManager.increasePosition.t.sol
Browse files Browse the repository at this point in the history
  • Loading branch information
noisekit committed Jan 30, 2025
1 parent 4c4d589 commit 04c41f2
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 60 deletions.
69 changes: 33 additions & 36 deletions contracts/position-manager-new-pool/src/PositionManager.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {ICoreProxy} from "@synthetixio/v3-contracts/1-main/ICoreProxy.sol";
import {IAccountProxy} from "@synthetixio/v3-contracts/1-main/IAccountProxy.sol";
import {ITreasuryMarketProxy} from "./ITreasuryMarketProxy.sol";

import {ERC2771Context} from "@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol";
import {ICollateralModule} from "@synthetixio/main/contracts/interfaces/ICollateralModule.sol";
import {IIssueUSDModule} from "@synthetixio/main/contracts/interfaces/IIssueUSDModule.sol";
import {IVaultModule} from "@synthetixio/main/contracts/interfaces/IVaultModule.sol";
import {IAccountModule} from "@synthetixio/main/contracts/interfaces/IAccountModule.sol";
import {IERC20} from "@synthetixio/core-contracts/contracts/interfaces/IERC20.sol";
import {IERC721Receiver} from "@synthetixio/core-contracts/contracts/interfaces/IERC721Receiver.sol";
import {IERC721Enumerable} from "@synthetixio/core-contracts/contracts/interfaces/IERC721Enumerable.sol";
import {IERC721} from "@synthetixio/core-contracts/contracts/interfaces/IERC721.sol";
import {ITreasuryMarketProxy} from "./ITreasuryMarketProxy.sol";
import {ISNX} from "./ISNX.sol";

contract PositionManagerNewPool {
Expand All @@ -20,9 +17,9 @@ contract PositionManagerNewPool {
error NotEnoughBalance(address walletAddress, address tokenAddress, uint256 requiredAmount, uint256 availableAmount);
error AccountExists();

address public CoreProxy;
address public AccountProxy;
address public TreasuryMarketProxy;
ICoreProxy public CoreProxy;
IAccountProxy public AccountProxy;
ITreasuryMarketProxy public TreasuryMarketProxy;

address public $SNX;
address public $sUSD;
Expand All @@ -37,9 +34,9 @@ contract PositionManagerNewPool {
address $sUSD_,
uint128 poolId_
) {
CoreProxy = CoreProxy_;
AccountProxy = AccountProxy_;
TreasuryMarketProxy = TreasuryMarketProxy_;
CoreProxy = ICoreProxy(CoreProxy_);
AccountProxy = IAccountProxy(AccountProxy_);
TreasuryMarketProxy = ITreasuryMarketProxy(TreasuryMarketProxy_);
$SNX = $SNX_;
$sUSD = $sUSD_;
poolId = poolId_;
Expand All @@ -52,14 +49,14 @@ contract PositionManagerNewPool {
*/
function getAccounts() public view returns (uint128[] memory accountIds) {
address msgSender = ERC2771Context._msgSender();
uint256 numberOfAccountTokens = IERC721(AccountProxy).balanceOf(msgSender);
uint256 numberOfAccountTokens = AccountProxy.balanceOf(msgSender);
if (numberOfAccountTokens == 0) {
return new uint128[](0);
}
accountIds = new uint128[](numberOfAccountTokens);
for (uint256 i = 0; i < numberOfAccountTokens; i++) {
// Retrieve the token/account ID at the index
uint256 accountId = IERC721Enumerable(AccountProxy).tokenOfOwnerByIndex(
uint256 accountId = AccountProxy.tokenOfOwnerByIndex(
//
msgSender,
i
Expand All @@ -75,13 +72,13 @@ contract PositionManagerNewPool {
*/
function setupPosition(uint256 snxAmount) public {
address msgSender = ERC2771Context._msgSender();
if (IERC721(AccountProxy).balanceOf(msgSender) > 0) {
if (AccountProxy.balanceOf(msgSender) > 0) {
// Do not allow to create more accounts
revert AccountExists();
}
uint128 accountId = IAccountModule(CoreProxy).createAccount();
uint128 accountId = CoreProxy.createAccount();
_increasePosition(accountId, snxAmount);
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
address(this),
msgSender,
Expand All @@ -96,14 +93,14 @@ contract PositionManagerNewPool {
*/
function increasePosition(uint128 accountId, uint256 snxAmount) public {
address msgSender = ERC2771Context._msgSender();
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
msgSender,
address(this),
uint256(accountId)
);
_increasePosition(accountId, snxAmount);
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
address(this),
msgSender,
Expand All @@ -120,32 +117,32 @@ contract PositionManagerNewPool {
address msgSender = ERC2771Context._msgSender();

// 1. Transfer Account NFT from the wallet
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
msgSender,
address(this),
uint256(accountId)
);

// 2. Transfer sUSD tokens from the wallet to repay the loan
uint256 currentLoan = ITreasuryMarketProxy(TreasuryMarketProxy).loanedAmount(accountId);
uint256 currentLoan = TreasuryMarketProxy.loanedAmount(accountId);
if (susdAmount > currentLoan) {
susdAmount = currentLoan;
}
_transferERC20($sUSD, susdAmount);

// 3. Repay account loan (must have enough sUSD that will be deposited to the Treasury Market)
ITreasuryMarketProxy(TreasuryMarketProxy).adjustLoan(
TreasuryMarketProxy.adjustLoan(
//
accountId,
currentLoan - susdAmount
);

// 4. Unsaddle
ITreasuryMarketProxy(TreasuryMarketProxy).unsaddle(accountId);
TreasuryMarketProxy.unsaddle(accountId);

// 5. Transfer Account NFT back to the owner
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
address(this),
msgSender,
Expand All @@ -161,22 +158,22 @@ contract PositionManagerNewPool {
address msgSender = ERC2771Context._msgSender();

// 1. Transfer Account NFT from the wallet
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
msgSender,
address(this),
uint256(accountId)
);

// 2. Get amount of available sUSD
uint256 susdAvailable = ICollateralModule(CoreProxy).getAccountAvailableCollateral(
uint256 susdAvailable = CoreProxy.getAccountAvailableCollateral(
//
accountId,
$sUSD
);
if (susdAvailable > 0) {
// 3. Withdraw all the available sUSD
ICollateralModule(CoreProxy).withdraw(
CoreProxy.withdraw(
//
accountId,
$sUSD,
Expand All @@ -191,14 +188,14 @@ contract PositionManagerNewPool {
}

// 5. Get amount of available SNX
uint256 snxAvailable = ICollateralModule(CoreProxy).getAccountAvailableCollateral(
uint256 snxAvailable = CoreProxy.getAccountAvailableCollateral(
//
accountId,
$SNX
);

// 6. Withdraw all the available SNX
ICollateralModule(CoreProxy).withdraw(
CoreProxy.withdraw(
//
accountId,
$SNX,
Expand All @@ -213,7 +210,7 @@ contract PositionManagerNewPool {
);

// 8. Transfer Account NFT back to the owner
IERC721(AccountProxy).safeTransferFrom(
AccountProxy.safeTransferFrom(
//
address(this),
msgSender,
Expand Down Expand Up @@ -301,17 +298,17 @@ contract PositionManagerNewPool {
_transferERC20($SNX, snxAmount);

// 2. Deposit SNX to the Core
ISNX($SNX).approve(CoreProxy, snxAmount);
ICollateralModule(CoreProxy).deposit(
ISNX($SNX).approve(address(CoreProxy), snxAmount);
CoreProxy.deposit(
//
accountId,
$SNX,
snxAmount
);

// 3. Delegate synthSNX to the Pool
uint256 currentPosition = IVaultModule(CoreProxy).getPositionCollateral(accountId, poolId, $SNX);
IVaultModule(CoreProxy).delegateCollateral(
uint256 currentPosition = CoreProxy.getPositionCollateral(accountId, poolId, $SNX);
CoreProxy.delegateCollateral(
//
accountId,
poolId,
Expand All @@ -321,7 +318,7 @@ contract PositionManagerNewPool {
);

// 4. Saddle account
ITreasuryMarketProxy(TreasuryMarketProxy).saddle(accountId);
TreasuryMarketProxy.saddle(accountId);
}

function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
pragma solidity ^0.8.21;

import {IAccountModule} from "@synthetixio/main/contracts/interfaces/IAccountModule.sol";
import {IAccountTokenModule} from "@synthetixio/main/contracts/interfaces/IAccountTokenModule.sol";
import {PositionManagerTest} from "./lib/PositionManagerTest.sol";
import "./lib/PositionManagerTest.sol";

contract PositionManager_getAccounts_Test is PositionManagerTest {
constructor() {
Expand All @@ -15,17 +13,17 @@ contract PositionManager_getAccounts_Test is PositionManagerTest {
vm.deal(ALICE, 1 ether);

vm.prank(ALICE);
uint128 ACCOUNT_ID_1 = IAccountModule(CoreProxy).createAccount();
uint128 ACCOUNT_ID_1 = CoreProxy.createAccount();

vm.prank(ALICE);
uint128 ACCOUNT_ID_2 = IAccountModule(CoreProxy).createAccount();
uint128 ACCOUNT_ID_2 = CoreProxy.createAccount();

vm.prank(ALICE);
uint128 ACCOUNT_ID_3 = IAccountModule(CoreProxy).createAccount();
uint128 ACCOUNT_ID_3 = CoreProxy.createAccount();

assertEq(ALICE, IAccountTokenModule(AccountProxy).ownerOf(ACCOUNT_ID_1));
assertEq(ALICE, IAccountTokenModule(AccountProxy).ownerOf(ACCOUNT_ID_2));
assertEq(ALICE, IAccountTokenModule(AccountProxy).ownerOf(ACCOUNT_ID_3));
assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID_1));
assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID_2));
assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID_3));

vm.prank(ALICE);
uint128[] memory accounts = positionManager.getAccounts();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pragma solidity ^0.8.21;

import "./lib/PositionManagerTest.sol";

contract PositionManager_increasePosition_Test is PositionManagerTest {
constructor() {
forkBlockNumber = 21684537;
}

function test_increasePosition() public {
uint128 ACCOUNT_ID = 0;
address ALICE = vm.addr(0xA11CE);
vm.label(ALICE, "0xA11CE");
vm.deal(ALICE, 1 ether);

vm.startPrank(address(CoreProxy));

$SNX.transfer(ALICE, 1000 ether);
$sUSD.transfer(ALICE, 1000 ether);

vm.startPrank(ALICE);

$SNX.approve(address(positionManager), 200 ether);

positionManager.setupPosition(200 ether);

ACCOUNT_ID = uint128(AccountProxy.tokenOfOwnerByIndex(ALICE, 0));
assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID));

assertEq(0, TreasuryMarketProxy.loanedAmount(ACCOUNT_ID));
assertEq(163.554286 ether, CoreProxy.getPositionDebt(ACCOUNT_ID, poolId, address($SNX))); // at C-Ratio 200%
assertEq(200 ether, CoreProxy.getPositionCollateral(ACCOUNT_ID, poolId, address($SNX)));
assertEq(0, CoreProxy.getAccountAvailableCollateral(ACCOUNT_ID, address($SNX)));

// Increase position by 500 SNX

AccountProxy.approve(address(positionManager), ACCOUNT_ID);
$SNX.approve(address(positionManager), 500 ether);
positionManager.increasePosition(ACCOUNT_ID, 500 ether);

assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID));

assertEq(0, TreasuryMarketProxy.loanedAmount(ACCOUNT_ID));
assertEq(572.440001 ether, CoreProxy.getPositionDebt(ACCOUNT_ID, poolId, address($SNX))); // at C-Ratio 200%
assertEq(700 ether, CoreProxy.getPositionCollateral(ACCOUNT_ID, poolId, address($SNX)));
assertEq(0, CoreProxy.getAccountAvailableCollateral(ACCOUNT_ID, address($SNX)));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
pragma solidity ^0.8.21;

import {ICollateralModule} from "@synthetixio/main/contracts/interfaces/ICollateralModule.sol";
import {IVaultModule} from "@synthetixio/main/contracts/interfaces/IVaultModule.sol";
import {IAccountTokenModule} from "@synthetixio/main/contracts/interfaces/IAccountTokenModule.sol";
import {IERC20} from "@synthetixio/core-contracts/contracts/interfaces/IERC20.sol";
import {PositionManagerTest} from "./lib/PositionManagerTest.sol";
import "./lib/PositionManagerTest.sol";

contract PositionManager_setupPosition_Test is PositionManagerTest {
constructor() {
Expand All @@ -17,24 +13,25 @@ contract PositionManager_setupPosition_Test is PositionManagerTest {
vm.label(ALICE, "0xA11CE");
vm.deal(ALICE, 1 ether);

vm.prank(CoreProxy);
IERC20($SNX).transfer(ALICE, 1000 ether);
vm.prank(CoreProxy);
IERC20($sUSD).transfer(ALICE, 1000 ether);
vm.prank(address(CoreProxy));
$SNX.transfer(ALICE, 1000 ether);
vm.prank(address(CoreProxy));
$sUSD.transfer(ALICE, 1000 ether);

vm.prank(ALICE);
IERC20($SNX).approve(address(positionManager), UINT256_MAX);
$SNX.approve(address(positionManager), 888 ether);

vm.prank(ALICE);
positionManager.setupPosition(888 ether);

// Retrieve ACCOUNT_ID via enumeration (index 0, since ALICE owns only one token).
ACCOUNT_ID = uint128(IAccountTokenModule(AccountProxy).tokenOfOwnerByIndex(ALICE, 0));
ACCOUNT_ID = uint128(AccountProxy.tokenOfOwnerByIndex(ALICE, 0));

assertEq(ALICE, IAccountTokenModule(AccountProxy).ownerOf(ACCOUNT_ID));
assertEq(ALICE, AccountProxy.ownerOf(ACCOUNT_ID));

assertEq(0, IVaultModule(CoreProxy).getPositionDebt(ACCOUNT_ID, poolId, $SNX));
assertEq(888 ether, IVaultModule(CoreProxy).getPositionCollateral(ACCOUNT_ID, poolId, $SNX));
assertEq(0, ICollateralModule(CoreProxy).getAccountAvailableCollateral(ACCOUNT_ID, $SNX));
assertEq(0, TreasuryMarketProxy.loanedAmount(ACCOUNT_ID));
assertEq(726.18102984 ether, CoreProxy.getPositionDebt(ACCOUNT_ID, poolId, address($SNX))); // at C-Ratio 200%
assertEq(888 ether, CoreProxy.getPositionCollateral(ACCOUNT_ID, poolId, address($SNX)));
assertEq(0, CoreProxy.getAccountAvailableCollateral(ACCOUNT_ID, address($SNX)));
}
}

0 comments on commit 04c41f2

Please sign in to comment.