mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Introduce registry of valid Augustus addresses
Set in constructor of BaseParaSwapSellAdapter and validates before swap. Created mock registry that only validates one address. Changed the test fixtures to accomodate registry and added two new tests. Updated deployment script. Registry address left as a placeholder in package.json since not known yet. Fixes MixBytes Warning 1.
This commit is contained in:
parent
9d1cb50d76
commit
4fe36c8fa4
|
@ -5,6 +5,7 @@ pragma experimental ABIEncoderV2;
|
|||
import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol';
|
||||
import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol';
|
||||
import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol';
|
||||
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||
|
||||
|
@ -16,10 +17,15 @@ import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detai
|
|||
abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
|
||||
using PercentageMath for uint256;
|
||||
|
||||
IParaSwapAugustusRegistry public immutable AUGUSTUS_REGISTRY;
|
||||
|
||||
constructor(
|
||||
ILendingPoolAddressesProvider addressesProvider
|
||||
ILendingPoolAddressesProvider addressesProvider,
|
||||
IParaSwapAugustusRegistry augustusRegistry
|
||||
) public BaseParaSwapAdapter(addressesProvider) {
|
||||
// This is only required to initialize BaseParaSwapAdapter
|
||||
// Do something on Augustus registry to check the right contract was passed
|
||||
require(!augustusRegistry.isValidAugustus(address(0)));
|
||||
AUGUSTUS_REGISTRY = augustusRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,6 +48,8 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
|
|||
uint256 amountToSwap,
|
||||
uint256 minAmountToReceive
|
||||
) internal returns (uint256 amountReceived) {
|
||||
require(AUGUSTUS_REGISTRY.isValidAugustus(address(augustus)), 'INVALID_AUGUSTUS');
|
||||
|
||||
{
|
||||
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
|
||||
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
|
||||
|
|
|
@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
|
|||
|
||||
import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol';
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol';
|
||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||
import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol';
|
||||
import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol';
|
||||
|
@ -16,8 +17,9 @@ import {ReentrancyGuard} from '../dependencies/openzeppelin/contracts/Reentrancy
|
|||
*/
|
||||
contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter, ReentrancyGuard {
|
||||
constructor(
|
||||
ILendingPoolAddressesProvider addressesProvider
|
||||
) public BaseParaSwapSellAdapter(addressesProvider) {
|
||||
ILendingPoolAddressesProvider addressesProvider,
|
||||
IParaSwapAugustusRegistry augustusRegistry
|
||||
) public BaseParaSwapSellAdapter(addressesProvider, augustusRegistry) {
|
||||
// This is only required to initialize BaseParaSwapSellAdapter
|
||||
}
|
||||
|
||||
|
|
7
contracts/interfaces/IParaSwapAugustusRegistry.sol
Normal file
7
contracts/interfaces/IParaSwapAugustusRegistry.sol
Normal file
|
@ -0,0 +1,7 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity 0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
interface IParaSwapAugustusRegistry {
|
||||
function isValidAugustus(address augustus) external view returns (bool);
|
||||
}
|
|
@ -8,7 +8,7 @@ import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
|
|||
import {MintableERC20} from '../tokens/MintableERC20.sol';
|
||||
|
||||
contract MockParaSwapAugustus is IParaSwapAugustus {
|
||||
MockParaSwapTokenTransferProxy _tokenTransferProxy;
|
||||
MockParaSwapTokenTransferProxy immutable TOKEN_TRANSFER_PROXY;
|
||||
bool _expectingSwap;
|
||||
address _expectedFromToken;
|
||||
address _expectedToToken;
|
||||
|
@ -17,11 +17,11 @@ contract MockParaSwapAugustus is IParaSwapAugustus {
|
|||
uint256 _receivedAmount;
|
||||
|
||||
constructor() public {
|
||||
_tokenTransferProxy = new MockParaSwapTokenTransferProxy();
|
||||
TOKEN_TRANSFER_PROXY = new MockParaSwapTokenTransferProxy();
|
||||
}
|
||||
|
||||
function getTokenTransferProxy() external view override returns (address) {
|
||||
return address(_tokenTransferProxy);
|
||||
return address(TOKEN_TRANSFER_PROXY);
|
||||
}
|
||||
|
||||
function expectSwap(
|
||||
|
@ -50,7 +50,7 @@ contract MockParaSwapAugustus is IParaSwapAugustus {
|
|||
require(toToken == _expectedToToken, 'Unexpected to token');
|
||||
require(fromAmount >= _expectedFromAmountMin && fromAmount <= _expectedFromAmountMax, 'From amount out of range');
|
||||
require(_receivedAmount >= toAmount, 'Received amount of tokens are less than expected');
|
||||
_tokenTransferProxy.transferFrom(fromToken, msg.sender, address(this), fromAmount);
|
||||
TOKEN_TRANSFER_PROXY.transferFrom(fromToken, msg.sender, address(this), fromAmount);
|
||||
MintableERC20(toToken).mint(_receivedAmount);
|
||||
IERC20(toToken).transfer(msg.sender, _receivedAmount);
|
||||
_expectingSwap = false;
|
||||
|
|
17
contracts/mocks/swap/MockParaSwapAugustusRegistry.sol
Normal file
17
contracts/mocks/swap/MockParaSwapAugustusRegistry.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity 0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {IParaSwapAugustusRegistry} from '../../interfaces/IParaSwapAugustusRegistry.sol';
|
||||
|
||||
contract MockParaSwapAugustusRegistry is IParaSwapAugustusRegistry {
|
||||
address immutable AUGUSTUS;
|
||||
|
||||
constructor(address augustus) public {
|
||||
AUGUSTUS = augustus;
|
||||
}
|
||||
|
||||
function isValidAugustus(address augustus) external view override returns (bool) {
|
||||
return augustus == AUGUSTUS;
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import {
|
|||
MockATokenFactory,
|
||||
MockFlashLoanReceiverFactory,
|
||||
MockParaSwapAugustusFactory,
|
||||
MockParaSwapAugustusRegistryFactory,
|
||||
MockStableDebtTokenFactory,
|
||||
MockVariableDebtTokenFactory,
|
||||
MockUniswapV2Router02Factory,
|
||||
|
@ -620,9 +621,20 @@ export const deployMockParaSwapAugustus = async (verify?: boolean) =>
|
|||
verify
|
||||
);
|
||||
|
||||
export const deployParaSwapLiquiditySwapAdapter = async (
|
||||
export const deployMockParaSwapAugustusRegistry = async (
|
||||
args: [tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new MockParaSwapAugustusRegistryFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.MockParaSwapAugustusRegistry,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployParaSwapLiquiditySwapAdapter = async (
|
||||
args: [tEthereumAddress, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new ParaSwapLiquiditySwapAdapterFactory(await getFirstSigner()).deploy(...args),
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
MockVariableDebtTokenFactory,
|
||||
MockUniswapV2Router02Factory,
|
||||
MockParaSwapAugustusFactory,
|
||||
MockParaSwapAugustusRegistryFactory,
|
||||
ParaSwapLiquiditySwapAdapterFactory,
|
||||
PriceOracleFactory,
|
||||
ReserveLogicFactory,
|
||||
|
@ -374,6 +375,14 @@ export const getMockParaSwapAugustus = async (address?: tEthereumAddress) =>
|
|||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockParaSwapAugustusRegistry = async (address?: tEthereumAddress) =>
|
||||
await MockParaSwapAugustusRegistryFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockParaSwapAugustusRegistry}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getParaSwapLiquiditySwapAdapter = async (address?: tEthereumAddress) =>
|
||||
await ParaSwapLiquiditySwapAdapterFactory.connect(
|
||||
address ||
|
||||
|
|
|
@ -88,6 +88,7 @@ export enum eContractid {
|
|||
UniswapRepayAdapter = 'UniswapRepayAdapter',
|
||||
FlashLiquidationAdapter = 'FlashLiquidationAdapter',
|
||||
MockParaSwapAugustus = 'MockParaSwapAugustus',
|
||||
MockParaSwapAugustusRegistry = 'MockParaSwapAugustusRegistry',
|
||||
ParaSwapLiquiditySwapAdapter = 'ParaSwapLiquiditySwapAdapter',
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
"dev:UniswapLiquiditySwapAdapter": "hardhat --network kovan deploy-UniswapLiquiditySwapAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c",
|
||||
"main:deployUniswapRepayAdapter": "hardhat --network main deploy-UniswapRepayAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D --weth 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"main:UniswapLiquiditySwapAdapter": "hardhat --network main deploy-UniswapLiquiditySwapAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D --weth 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"main:ParaSwapLiquiditySwapAdapter": "hardhat --network main deploy-ParaSwapLiquiditySwapAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5",
|
||||
"main:ParaSwapLiquiditySwapAdapter": "hardhat --network main deploy-ParaSwapLiquiditySwapAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --augustusRegistry 0x0000000000000000000000000000000000000000",
|
||||
"kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Aave",
|
||||
"ropsten:verify": "npm run hardhat:ropsten verify:general -- --all --pool Aave",
|
||||
"mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave",
|
||||
|
|
|
@ -8,8 +8,9 @@ const CONTRACT_NAME = 'ParaSwapLiquiditySwapAdapter';
|
|||
|
||||
task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`)
|
||||
.addParam('provider', 'Address of the LendingPoolAddressesProvider')
|
||||
.addParam('augustusRegistry', 'Address of ParaSwap AugustusRegistry')
|
||||
.addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`)
|
||||
.setAction(async ({ provider, verify }, localBRE) => {
|
||||
.setAction(async ({ provider, augustusRegistry, verify }, localBRE) => {
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
if (!localBRE.network.config.chainId) {
|
||||
|
@ -19,10 +20,10 @@ task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`)
|
|||
console.log(`\n- ${CONTRACT_NAME} deployment`);
|
||||
const adapter = await new ParaSwapLiquiditySwapAdapterFactory(
|
||||
await getFirstSigner()
|
||||
).deploy(provider);
|
||||
).deploy(provider, augustusRegistry);
|
||||
await adapter.deployTransaction.wait();
|
||||
console.log(`${CONTRACT_NAME}.address`, adapter.address);
|
||||
await verifyContract(adapter.address, [provider]);
|
||||
await verifyContract(adapter.address, [provider, augustusRegistry]);
|
||||
|
||||
console.log(`\tFinished ${CONTRACT_NAME} deployment`);
|
||||
});
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
deployUniswapRepayAdapter,
|
||||
deployFlashLiquidationAdapter,
|
||||
deployMockParaSwapAugustus,
|
||||
deployMockParaSwapAugustusRegistry,
|
||||
deployParaSwapLiquiditySwapAdapter,
|
||||
authorizeWETHGateway,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
|
@ -286,9 +287,11 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
await deployUniswapRepayAdapter(adapterParams);
|
||||
await deployFlashLiquidationAdapter(adapterParams);
|
||||
|
||||
await deployMockParaSwapAugustus();
|
||||
const augustus = await deployMockParaSwapAugustus();
|
||||
|
||||
await deployParaSwapLiquiditySwapAdapter([addressesProvider.address]);
|
||||
const augustusRegistry = await deployMockParaSwapAugustusRegistry([augustus.address]);
|
||||
|
||||
await deployParaSwapLiquiditySwapAdapter([addressesProvider.address, augustusRegistry.address]);
|
||||
|
||||
await deployWalletBalancerProvider();
|
||||
|
||||
|
|
|
@ -6,9 +6,13 @@ import {
|
|||
getSignatureFromTypedData,
|
||||
buildParaSwapLiquiditySwapParams,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
import { getMockParaSwapAugustus } from '../../helpers/contracts-getters';
|
||||
import {
|
||||
getMockParaSwapAugustus,
|
||||
getMockParaSwapAugustusRegistry,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import { deployParaSwapLiquiditySwapAdapter } from '../../helpers/contracts-deployments';
|
||||
import { MockParaSwapAugustus } from '../../types/MockParaSwapAugustus';
|
||||
import { MockParaSwapAugustusRegistry } from '../../types/MockParaSwapAugustusRegistry';
|
||||
import { Zero } from '@ethersproject/constants';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { DRE, evmRevert, evmSnapshot } from '../../helpers/misc-utils';
|
||||
|
@ -23,10 +27,12 @@ const { expect } = require('chai');
|
|||
|
||||
makeSuite('ParaSwap adapters', (testEnv: TestEnv) => {
|
||||
let mockAugustus: MockParaSwapAugustus;
|
||||
let mockAugustusRegistry: MockParaSwapAugustusRegistry;
|
||||
let evmSnapshotId: string;
|
||||
|
||||
before(async () => {
|
||||
mockAugustus = await getMockParaSwapAugustus();
|
||||
mockAugustusRegistry = await getMockParaSwapAugustusRegistry();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
@ -43,13 +49,25 @@ makeSuite('ParaSwap adapters', (testEnv: TestEnv) => {
|
|||
const { addressesProvider } = testEnv;
|
||||
await deployParaSwapLiquiditySwapAdapter([
|
||||
addressesProvider.address,
|
||||
mockAugustusRegistry.address,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should revert if not valid addresses provider', async () => {
|
||||
await expect(
|
||||
deployParaSwapLiquiditySwapAdapter([
|
||||
mockAugustus.address,
|
||||
mockAugustus.address, // any invalid contract can be used here
|
||||
mockAugustusRegistry.address,
|
||||
])
|
||||
).to.be.reverted;
|
||||
});
|
||||
|
||||
it('should revert if not valid augustus registry', async () => {
|
||||
const { addressesProvider } = testEnv;
|
||||
await expect(
|
||||
deployParaSwapLiquiditySwapAdapter([
|
||||
addressesProvider.address,
|
||||
mockAugustus.address, // any invalid contract can be used here
|
||||
])
|
||||
).to.be.reverted;
|
||||
});
|
||||
|
@ -1637,6 +1655,49 @@ makeSuite('ParaSwap adapters', (testEnv: TestEnv) => {
|
|||
).to.be.revertedWith('MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE');
|
||||
});
|
||||
|
||||
it('should revert if wrong address used for Augustus', async () => {
|
||||
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
||||
const user = users[0].signer;
|
||||
const userAddress = users[0].address;
|
||||
|
||||
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
||||
|
||||
const daiPrice = await oracle.getAssetPrice(dai.address);
|
||||
const expectedDaiAmount = await convertToCurrencyDecimals(
|
||||
dai.address,
|
||||
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
||||
);
|
||||
|
||||
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
||||
|
||||
// User will swap liquidity aEth to aDai
|
||||
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
||||
|
||||
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
||||
'swap',
|
||||
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
||||
);
|
||||
|
||||
await expect(
|
||||
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
||||
weth.address,
|
||||
dai.address,
|
||||
amountWETHtoSwap,
|
||||
expectedDaiAmount,
|
||||
0,
|
||||
mockAugustusCalldata,
|
||||
oracle.address, // using arbitrary contract instead of mock Augustus
|
||||
{
|
||||
amount: 0,
|
||||
deadline: 0,
|
||||
v: 0,
|
||||
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||
}
|
||||
)
|
||||
).to.be.revertedWith('INVALID_AUGUSTUS');
|
||||
});
|
||||
|
||||
it('should bubble up errors from Augustus', async () => {
|
||||
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
||||
const user = users[0].signer;
|
||||
|
|
Loading…
Reference in New Issue
Block a user