Skip to content
Draft
Show file tree
Hide file tree
Changes from 16 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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"prettier-plugin-solidity": "^1.0.0-beta.19"
},
"dependencies": {
"@paraswap/sdk": "^6.2.1",
"@paraswap/core": "^2.4.0",
"@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
53 changes: 42 additions & 11 deletions scripts/psp.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ 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,
version: "6.2",
});

// 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 +59,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 +99,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,21 +125,23 @@ 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,
destToken: to,
destDecimals: TO_DECIMALS,
amount: amount,
side: method,
userAddress: user,
version: "6.2",
...(MAX
? {
options: {
excludeContractMethods: [...excludedMethod],
includeContractMethods: [...includedMethods],
},
}
: {}),
Expand Down Expand Up @@ -145,6 +174,8 @@ async function main(from, to, method, amount, user) {
priceRoute,
userAddress: user,
partner: "aave",
isDirectFeeTransfer: true,
takeSurplus: true,
},
{ ignoreChecks: true }
);
Expand Down
2 changes: 2 additions & 0 deletions src/contracts/BaseParaSwapAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAd
import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol';
import {IPriceOracleGetter} from '@aave/core-v3/contracts/interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol';
import {SafeMath} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeMath.sol';
import {Ownable} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/Ownable.sol';
import {IFlashLoanReceiverBase} from '../interfaces/IFlashLoanReceiverBase.sol';

Expand All @@ -18,6 +19,7 @@ import {IFlashLoanReceiverBase} from '../interfaces/IFlashLoanReceiverBase.sol';
* @author Jason Raymond Bell
*/
abstract contract BaseParaSwapAdapter is IFlashLoanReceiverBase, Ownable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Detailed;
using SafeERC20 for IERC20WithPermit;
Expand Down
31 changes: 14 additions & 17 deletions src/contracts/BaseParaSwapBuyAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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 {SafeMath} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeMath.sol';
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol';

Expand All @@ -14,8 +14,9 @@ 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 SafeMath for uint256;
Copy link
Contributor

Choose a reason for hiding this comment

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

SafeMath is not needed since we are >0.8.0

using SafeERC20 for IERC20Detailed;

IParaSwapAugustusRegistry public immutable AUGUSTUS_REGISTRY;

Expand Down Expand Up @@ -48,12 +49,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 @@ -62,9 +59,10 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
uint256 fromAssetPrice = _getPrice(address(assetToSwapFrom));
uint256 toAssetPrice = _getPrice(address(assetToSwapTo));

uint256 expectedMaxAmountToSwap = ((amountToReceive *
(toAssetPrice * (10 ** fromAssetDecimals))) / (fromAssetPrice * (10 ** toAssetDecimals)))
.percentMul(PercentageMath.PERCENTAGE_FACTOR + MAX_SLIPPAGE_PERCENT);
uint256 expectedMaxAmountToSwap = amountToReceive
.mul(toAssetPrice.mul(10 ** fromAssetDecimals))
.div(fromAssetPrice.mul(10 ** toAssetDecimals))
.percentMul(PercentageMath.PERCENTAGE_FACTOR.add(MAX_SLIPPAGE_PERCENT));

require(maxAmountToSwap <= expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage');
}
Expand All @@ -73,14 +71,13 @@ 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
// calldata, not overlapping with the first 4 bytes (function selector).
require(
toAmountOffset >= 4 && toAmountOffset <= buyCalldata.length - 32,
toAmountOffset >= 4 && toAmountOffset <= buyCalldata.length.sub(32),
'TO_AMOUNT_OFFSET_OUT_OF_RANGE'
);
// Overwrite the toAmount with the correct amount for the buy.
Expand All @@ -90,7 +87,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,12 +96,12 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
}
}
// Reset allowance
assetToSwapFrom.safeApprove(tokenTransferProxy, 0);
assetToSwapFrom.safeApprove(augustus, 0);

uint256 balanceAfterAssetFrom = assetToSwapFrom.balanceOf(address(this));
amountSold = balanceBeforeAssetFrom - balanceAfterAssetFrom;
require(amountSold <= maxAmountToSwap, 'WRONG_BALANCE_AFTER_SWAP');
amountBought = assetToSwapTo.balanceOf(address(this)) - balanceBeforeAssetTo;
amountBought = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo);
require(amountBought >= amountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED');

emit Bought(address(assetToSwapFrom), address(assetToSwapTo), amountSold, amountBought);
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.

Loading