Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ libs = ['lib']
remappings = [
]
ffi = true
evm_version = "cancun"

[rpc_endpoints]
mainnet = "${RPC_MAINNET}"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"prettier-plugin-solidity": "^1.0.0-beta.19"
},
"dependencies": {
"@paraswap/sdk": "^6.2.1",
"@paraswap/sdk": "^6.11.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this new dependency?

Copy link
Author

@CheyenneAtapour CheyenneAtapour Oct 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

"axios": "^1.1.3",
"ethers": "^5.7.2",
"object-hash": "^3.0.0"
Expand Down
48 changes: 37 additions & 11 deletions scripts/psp.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ const TO_DECIMALS = Number(args[9]);
// generate a hash for input parameters to cache response and not spam psp sdk
const hash = objectHash(args);

const paraSwapMin = constructSimpleSDK({ chainId: CHAIN_ID, axios });
const paraSwapMin = constructSimpleSDK({
chainId: CHAIN_ID,
axios,
});

// https://github.com/aave/aave-utilities/blob/master/packages/contract-helpers/src/paraswap-liquiditySwapAdapter-contract/index.ts#L19
function augustusFromAmountOffsetFromCalldata(calldata) {
Expand All @@ -55,16 +58,29 @@ function augustusFromAmountOffsetFromCalldata(calldata) {
return 68; // 4 + 2 * 32
case "0x46c67b6d": // Augustus V5 megaSwap
return 68; // 4 + 2 * 32
case "0xb22f4db8": // directBalancerV2GivenInSwap
case "0xb22f4db8": // Augustus V5 directBalancerV2GivenInSwap
return 68; // 4 + 2 * 32
case "0x19fc5be0": // directBalancerV2GivenOutSwap
case "0x19fc5be0": // Augustus V5 directBalancerV2GivenOutSwap
return 68; // 4 + 2 * 32
case "0x3865bde6": // directCurveV1Swap
case "0x3865bde6": // Augustus V5 directCurveV1Swap
return 68; // 4 + 2 * 32
case "0x58f15100": // directCurveV2Swap
case "0x58f15100": // Augustus V5 directCurveV2Swap
return 68; // 4 + 2 * 32
case "0xa6866da9": // directUniV3Swap
case "0xa6866da9": // Augustus V5 directUniV3Swap
return 68; // 4 + 2 * 32
case "0xe3ead59e": // Augustus V6 swapExactAmountIn
return 100; // 4 + 3 * 32
case "0xd85ca173": // Augustus V6 swapExactAmountInOnBalancerV2
return 4; // 4 + 0 * 32
case "0x1a01c532": // Augustus V6 swapExactAmountInOnCurveV1
return 132; // 4 + 4 * 32
case "0xe37ed256": // Augustus V6 swapExactAmountInOnCurveV2
return 196; // 4 + 6 * 32
case "0xe8bb3b6c": // Augustus V6 swapExactAmountInOnUniswapV2
return 164; // 4 + 4 * 32
case "0x876a02f6": // Augustus V6 swapExactAmountInOnUniswapV3
return 164; // 4 + 4 * 32
case "0x987e7d8e": // Augustus V6 swapExactAmountInOutOnMakerPSM
default:
throw new Error("Unrecognized function selector for Augustus");
}
Expand All @@ -82,8 +98,18 @@ const augustusToAmountOffsetFromCalldata = (calldata) => {
case "0xb66bcbac": // Augustus V5 buy (old)
case "0x35326910": // Augustus V5 buy
return 164; // 4 + 5 * 32
case "0x87a63926": // directUniV3Buy
case "0x87a63926": // Augustus V5 directUniV3Buy
return 68; // 4 + 2 * 32
case "0x7f457675": // Augustus V6 swapExactAmountOut
return 132; // 4 + 4 * 32
case "0xd6ed22e6": // Augustus V6 swapExactAmountOutOnBalancerV2
return 36; // 4 + 1 * 32
case "0xa76f4eb6": // Augustus V6 swapExactAmountOutOnUniswapV2
return 196; // 4 + 6 * 32
case "0x5e94e28d": // Augustus V6 swapExactAmountOutOnUniswapV3
return 196; // 4 + 6 * 32
case "0x987e7d8e": // Augustus V6 swapExactAmountInOutOnMakerPSM
return 100; // 4 + 3 * 32
default:
throw new Error("Unrecognized function selector for Augustus");
}
Expand All @@ -98,10 +124,10 @@ async function main(from, to, method, amount, user) {
return;
}
// distinguish between exactOut and exactInoutdMethod
const excludedMethod =
const includedMethods =
method === "SELL"
? [ContractMethod.simpleSwap]
: [ContractMethod.simpleBuy, ContractMethod.directUniV3Buy];
? [ContractMethod.swapExactAmountIn]
: [ContractMethod.swapExactAmountOut];
const priceRoute = await paraSwapMin.swap.getRate({
srcToken: from,
srcDecimals: FROM_DECIMALS,
Expand All @@ -112,7 +138,7 @@ async function main(from, to, method, amount, user) {
...(MAX
? {
options: {
excludeContractMethods: [...excludedMethod],
includeContractMethods: [...includedMethods],
},
}
: {}),
Expand Down
18 changes: 6 additions & 12 deletions src/contracts/BaseParaSwapBuyAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {PercentageMath} from '@aave/core-v3/contracts/protocol/libraries/math/Pe
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol';
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol';

Expand All @@ -14,8 +13,8 @@ import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol';
* @notice Implements the logic for buying tokens on ParaSwap
*/
abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
using SafeERC20 for IERC20Detailed;
using PercentageMath for uint256;
using SafeERC20 for IERC20Detailed;

IParaSwapAugustusRegistry public immutable AUGUSTUS_REGISTRY;

Expand Down Expand Up @@ -48,12 +47,8 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
uint256 maxAmountToSwap,
uint256 amountToReceive
) internal returns (uint256 amountSold, uint256 amountBought) {
(bytes memory buyCalldata, IParaSwapAugustus augustus) = abi.decode(
paraswapData,
(bytes, IParaSwapAugustus)
);

require(AUGUSTUS_REGISTRY.isValidAugustus(address(augustus)), 'INVALID_AUGUSTUS');
(bytes memory buyCalldata, address augustus) = abi.decode(paraswapData, (bytes, address));
require(AUGUSTUS_REGISTRY.isValidAugustus(augustus), 'INVALID_AUGUSTUS');

{
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
Expand All @@ -73,8 +68,7 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
require(balanceBeforeAssetFrom >= maxAmountToSwap, 'INSUFFICIENT_BALANCE_BEFORE_SWAP');
uint256 balanceBeforeAssetTo = assetToSwapTo.balanceOf(address(this));

address tokenTransferProxy = augustus.getTokenTransferProxy();
assetToSwapFrom.safeApprove(tokenTransferProxy, maxAmountToSwap);
assetToSwapFrom.safeApprove(augustus, maxAmountToSwap);

if (toAmountOffset != 0) {
// Ensure 256 bit (32 bytes) toAmountOffset value is within bounds of the
Expand All @@ -90,7 +84,7 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
mstore(add(buyCalldata, add(toAmountOffset, 32)), amountToReceive)
}
}
(bool success, ) = address(augustus).call(buyCalldata);
(bool success, ) = augustus.call(buyCalldata);
if (!success) {
// Copy revert reason from call
assembly {
Expand All @@ -99,7 +93,7 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
}
}
// Reset allowance
assetToSwapFrom.safeApprove(tokenTransferProxy, 0);
assetToSwapFrom.safeApprove(augustus, 0);

uint256 balanceAfterAssetFrom = assetToSwapFrom.balanceOf(address(this));
amountSold = balanceBeforeAssetFrom - balanceAfterAssetFrom;
Expand Down
1 change: 0 additions & 1 deletion src/contracts/ParaSwapDebtSwapAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAd
import {ReentrancyGuard} from 'aave-v3-periphery/contracts/dependencies/openzeppelin/ReentrancyGuard.sol';
import {BaseParaSwapBuyAdapter} from './BaseParaSwapBuyAdapter.sol';
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol';
import {IFlashLoanReceiver} from '../interfaces/IFlashLoanReceiver.sol';
import {ICreditDelegationToken} from '../interfaces/ICreditDelegationToken.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';
Expand Down
1 change: 0 additions & 1 deletion src/contracts/ParaSwapDebtSwapAdapterV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pragma solidity ^0.8.10;
import {ParaSwapDebtSwapAdapter} from './ParaSwapDebtSwapAdapter.sol';
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol';
import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol';

/**
Expand Down
2 changes: 0 additions & 2 deletions src/contracts/ParaSwapDebtSwapAdapterV3GHO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ pragma solidity ^0.8.10;
import {ParaSwapDebtSwapAdapterV3} from './ParaSwapDebtSwapAdapterV3.sol';
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol';
import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol';
import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
import {IERC3156FlashBorrower} from '../interfaces/IERC3156FlashBorrower.sol';
Expand Down
6 changes: 0 additions & 6 deletions src/interfaces/IParaSwapAugustus.sol

This file was deleted.

98 changes: 49 additions & 49 deletions tests/DebtSwapV2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract DebtSwapV2Test is BaseTest {

function setUp() public override {
super.setUp();
vm.createSelectFork(vm.rpcUrl('mainnet'), 17706839);
vm.createSelectFork(vm.rpcUrl('mainnet'), 21027710);

debtSwapAdapter = new ParaSwapDebtSwapAdapterV2(
IPoolAddressesProvider(address(AaveV2Ethereum.POOL_ADDRESSES_PROVIDER)),
Expand Down Expand Up @@ -58,16 +58,16 @@ contract DebtSwapV2Test is BaseTest {
}

function test_revert_debtSwap_without_extra_collateral() public {
address aToken = AaveV2EthereumAssets.DAI_A_TOKEN;
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.LUSD_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.LUSD_V_TOKEN;
address aToken = AaveV2EthereumAssets.WETH_A_TOKEN;
address debtAsset = AaveV2EthereumAssets.WETH_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.DAI_V_TOKEN;

uint256 supplyAmount = 120e18;
uint256 borrowAmount = 80e18;
uint256 supplyAmount = 12e18;
uint256 borrowAmount = 8e18;

// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 75% by withdrawing (80 > 75 > 67).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 75;
// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 83% by withdrawing (86 > 83 > 82.5).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 83;

// Deal some debtAsset to cover the premium and any 1 wei rounding errors on withdrawal.
deal(debtAsset, address(debtSwapAdapter), 1e18);
Expand Down Expand Up @@ -121,18 +121,18 @@ contract DebtSwapV2Test is BaseTest {

/**
* 1. supply 200000 DAI
* 2. borrow 1000 DAI
* 3. swap whole DAI debt to LUSD debt
* 2. borrow 10 DAI
* 3. swap whole DAI debt to USDC debt
*/
function test_debtSwap_swapHalf() public {
vm.startPrank(user);
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address debtToken = AaveV2EthereumAssets.DAI_V_TOKEN;
address newDebtAsset = AaveV2EthereumAssets.LUSD_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.LUSD_V_TOKEN;
address newDebtAsset = AaveV2EthereumAssets.USDC_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.USDC_V_TOKEN;

uint256 supplyAmount = 200000 ether;
uint256 borrowAmount = 1000 ether;
uint256 borrowAmount = 10 ether;

_supply(AaveV2Ethereum.POOL, supplyAmount, debtAsset);
_borrow(AaveV2Ethereum.POOL, borrowAmount, debtAsset);
Expand Down Expand Up @@ -180,11 +180,11 @@ contract DebtSwapV2Test is BaseTest {
vm.startPrank(user);
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address debtToken = AaveV2EthereumAssets.DAI_V_TOKEN;
address newDebtAsset = AaveV2EthereumAssets.LUSD_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.LUSD_V_TOKEN;
address newDebtAsset = AaveV2EthereumAssets.USDC_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.USDC_V_TOKEN;

uint256 supplyAmount = 200000 ether;
uint256 borrowAmount = 1000 ether;
uint256 borrowAmount = 10 ether;

_supply(AaveV2Ethereum.POOL, supplyAmount, debtAsset);
_borrow(AaveV2Ethereum.POOL, borrowAmount, debtAsset);
Expand Down Expand Up @@ -229,23 +229,23 @@ contract DebtSwapV2Test is BaseTest {
_invariant(address(debtSwapAdapter), debtAsset, newDebtAsset);
}

function test_debtSwap_swapAll_BUSD() public {
address vBUSD_WHALE = 0x154AF3A2071363D3fFcDB43744C2a906d8EB856a;
vm.startPrank(vBUSD_WHALE); // vBUSD Whale
address debtAsset = AaveV2EthereumAssets.BUSD_UNDERLYING;
address debtToken = AaveV2EthereumAssets.BUSD_V_TOKEN;
function test_debtSwap_swapAll_USDC() public {
address vUSDC_WHALE = 0xd262b944e2EfFcA0855C43023D3f1843B0Ee6fB1;
vm.startPrank(vUSDC_WHALE); // vUSDC Whale
address debtAsset = AaveV2EthereumAssets.USDC_UNDERLYING;
address debtToken = AaveV2EthereumAssets.USDC_V_TOKEN;
address newDebtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.DAI_V_TOKEN;

uint256 borrowAmount = IERC20Detailed(debtToken).balanceOf(vBUSD_WHALE);
uint256 borrowAmount = IERC20Detailed(debtToken).balanceOf(vUSDC_WHALE);

// add some margin to account for accumulated debt
uint256 repayAmount = (borrowAmount * 101) / 100;
PsPResponse memory psp = _fetchPSPRoute(
newDebtAsset,
debtAsset,
repayAmount,
vBUSD_WHALE,
vUSDC_WHALE,
false,
true
);
Expand All @@ -272,26 +272,26 @@ contract DebtSwapV2Test is BaseTest {

debtSwapAdapter.swapDebt(debtSwapParams, cd, collateralATokenPermit);

uint256 vDEBT_TOKENBalanceAfter = IERC20Detailed(debtToken).balanceOf(vBUSD_WHALE);
uint256 vNEWDEBT_TOKENBalanceAfter = IERC20Detailed(newDebtToken).balanceOf(vBUSD_WHALE);
uint256 vDEBT_TOKENBalanceAfter = IERC20Detailed(debtToken).balanceOf(vUSDC_WHALE);
uint256 vNEWDEBT_TOKENBalanceAfter = IERC20Detailed(newDebtToken).balanceOf(vUSDC_WHALE);
assertEq(vDEBT_TOKENBalanceAfter, 0);
assertLe(vNEWDEBT_TOKENBalanceAfter, psp.srcAmount);
_invariant(address(debtSwapAdapter), debtAsset, newDebtAsset);
}

function test_debtSwap_extra_Collateral() public {
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.LUSD_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.LUSD_V_TOKEN;
address debtAsset = AaveV2EthereumAssets.WETH_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.DAI_V_TOKEN;
address extraCollateralAsset = debtAsset;
address extraCollateralAToken = AaveV2EthereumAssets.DAI_A_TOKEN;
address extraCollateralAToken = AaveV2EthereumAssets.WETH_A_TOKEN;

uint256 supplyAmount = 120e18;
uint256 borrowAmount = 80e18;
uint256 extraCollateralAmount = 1000e18;
uint256 supplyAmount = 12e18;
uint256 borrowAmount = 8e18;
uint256 extraCollateralAmount = 100e18;

// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 75% by withdrawing (80 > 75 > 67).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 75;
// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 83% by withdrawing (86 > 83 > 82.5).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 83;

// Deal some debtAsset to cover the premium and any 1 wei rounding errors on withdrawal.
deal(debtAsset, address(debtSwapAdapter), 1e18);
Expand Down Expand Up @@ -346,18 +346,18 @@ contract DebtSwapV2Test is BaseTest {
}

function test_debtSwap_extra_Collateral_permit() public {
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.LUSD_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.LUSD_V_TOKEN;
address debtAsset = AaveV2EthereumAssets.WETH_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.DAI_V_TOKEN;
address extraCollateralAsset = debtAsset;
address extraCollateralAToken = AaveV2EthereumAssets.DAI_A_TOKEN;
address extraCollateralAToken = AaveV2EthereumAssets.WETH_A_TOKEN;

uint256 supplyAmount = 120e18;
uint256 borrowAmount = 80e18;
uint256 extraCollateralAmount = 1000e18;
uint256 supplyAmount = 12e18;
uint256 borrowAmount = 8e18;
uint256 extraCollateralAmount = 100e18;

// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 75% by withdrawing (80 > 75 > 67).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 75;
// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 83% by withdrawing (86 > 83 > 82.5).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 83;

// Deal some debtAsset to cover the premium and any 1 wei rounding errors on withdrawal.
deal(debtAsset, address(debtSwapAdapter), 1e18);
Expand Down Expand Up @@ -413,18 +413,18 @@ contract DebtSwapV2Test is BaseTest {

function test_debtSwap_extra_Collateral_same_as_new_debt() public {
// We'll use the debtAsset & supplyAmount as extra collateral too.
address debtAsset = AaveV2EthereumAssets.DAI_UNDERLYING;
address debtAsset = AaveV2EthereumAssets.WETH_UNDERLYING;
address newDebtAsset = AaveV2EthereumAssets.USDC_UNDERLYING;
address newDebtToken = AaveV2EthereumAssets.USDC_V_TOKEN;
address extraCollateralAsset = newDebtAsset;
address extraCollateralAToken = AaveV2EthereumAssets.USDC_A_TOKEN;

uint256 supplyAmount = 120e18;
uint256 borrowAmount = 80e18;
uint256 supplyAmount = 12e18;
uint256 borrowAmount = 8e18;
uint256 extraCollateralAmount = 1000e6;

// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 75% by withdrawing (80 > 75 > 67).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 75;
// We want to end with LT > utilisation > LTV, so we pump up the utilisation to 75% by withdrawing (86 > 83 > 82.5).
uint256 withdrawAmount = supplyAmount - (borrowAmount * 100) / 83;

// Deal some debtAsset to cover the premium and any 1 wei rounding errors on withdrawal.
deal(debtAsset, address(debtSwapAdapter), 1e18);
Expand Down
Loading