Skip to content

Commit

Permalink
Fix initiation of CowSwap swaps (#61)
Browse files Browse the repository at this point in the history
chore: 2nd security audit
fix: HH task liq-init-swap needs to set trader to CowSwapDex, not the Liquidator
fix: CowSwapDex initiateSwap takes fee off sell amount
chore: removed onlySign flag from CowSwap dex swap data
chore: removed SwapInitiated event from CowSwapSeller
chore: removes warning issues and updates liquidator tests (#62)
Co-authored-by: doncesarts <doncesarts@gmail.com>
  • Loading branch information
naddison36 and doncesarts authored Oct 21, 2022
1 parent 0860064 commit 4f41f30
Show file tree
Hide file tree
Showing 25 changed files with 262 additions and 186 deletions.
10 changes: 8 additions & 2 deletions 3CrvConvexVaults.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ The first set of mStable meta vaults are for staking 3Pool-based (3Crv) [Curve](

# Contracts

![savePlusDeployment](./docs/savePlusDeployment.png)
Dependencies

## DAI/USDC/USDT 3Pooler Meta Vaults
![Convex 3Crv Dependencies](./docs/convex3CrvDependencies.png)

Mainnet Deployment

![Convex 3Crv contracts](./docs/convex3CrvContracts.png)

## DAI/USDC/USDT 3Pool Meta Vaults

Abstract ERC-4626 vaults with DAI, USDC or USDT asset invested in Curve's [3Pool](https://curve.fi/3pool), and then the 3Pool LP token (3Crv) is invested in an underlying 3Pool-based (3Crv) Meta Vault.

Expand Down
2 changes: 1 addition & 1 deletion MetaVaultAudit.md → FirstMetaVaultAudit.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Meta Vaults Security Audit Scope
# First Meta Vaults Security Audit

Scope of the security audit of [mStable](https://mstable.org/)'s new Meta Vaults by [Hacken](https://hacken.io/), September 2022.

Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,15 @@ export NODE_URL=https://mainnet.infura.io/v3/yourApiKey
yarn task token-transfer --network mainnet --asset MTA --recipient mStableDAO -- amount 1000
```

<br />
## Other mStable Meta Vault repositories

- https://github.com/mstable/mStable-defender
- https://github.com/mstable/metavault-subgraph
- https://github.com/mstable/frontend
- https://github.com/mstable/mStable-data
- https://github.com/mstable/mStable-process-docs/tree/main/vaults

mStable version 1 app and documentation.
## mStable version 1 app and documentation.

- https://mstable.org
- https://app.mstable.org
Expand Down
82 changes: 82 additions & 0 deletions SecondMetaVaultAudit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Second Meta Vaults Security Audit

Scope of the security audit of [mStable](https://mstable.org/)'s new Meta Vaults, October 2022.

# Logic

See [3Crv Convex Vaults](./3CrvConvexVaults.md) for an explanation of what the different vaults do and how value flows between them.

# Code

Only the high risk contracts will be audited. Simpler contracts that have been previously audited are out of scope given the tight timeframes.

All code is in the [metavaults](https://github.com/mstable/metavaults) private repository with tag [v0.0.3](https://github.com/mstable/metavaults/tree/v0.0.3).

# Contract scope

All contract are under the [contracts](./contracts/) folder.

## In scope

- [peripheral](./contracts/peripheral/)
- [Cowswap](./contracts/peripheral/Cowswap) the [CowSwapSeller](./contracts/peripheral/Cowswap/CowSwapSeller.sol) contract that integrates with CoW Swap.
- [shares](./contracts/shared/) just the [SingleSlotMapper](./contracts/shared/SingleSlotMapper.sol) contract as it has not been audited. The others have been through multiple audits.
- [vault](./contracts/vault) all vault contract except the ones listed below in the out of scope section.
- [swap](./contracts/vault/swap/) only [CowSwapDex](./contracts/vault/swap/CowSwapDex.sol) is in scope.

## Out of scope

Any contracts in the following are out of scope as they have previously been audited or are just used for testing.

- [governance](./contracts/governance) all out of scope as perviously audited.
- [interfaces](./contracts/interfaces) contract interfaces.
- [nexus](./contracts/nexus) all out of scope as perviously audited.
- [peripheral](./contracts/peripheral/)
- [Convex](./contracts/peripheral/Convex) are just interfaces.
- [Curve](./contracts/peripheral/Curve) are interfaces, libraries or testing contracts. The libraries are ports of Curve's Vyper code with gas optimizations. They are stateless so are not a high risk of containing security issues. Given their logic complexity and they have previously been audited, they are out of scope of this audit.
- [OneInch](./contracts/peripheral/OneInch) are just interfaces and will not be initially used.
- [token](./contracts/tokens) all out scope as perviously audited.
- [upgradability](./contracts/upgradability) all out of scope as perviously audited.
- [vault](./contracts/vault) any BasicVaults are out of scope as they are just used for testing. Specifically, `PeriodicAllocationBasicVault`, `SameAssetUnderlyingsBasicVault`, `PerfFeeBasicVault`, `LiquidatorBasicVault`, `LiquidatorStreamBasicVault`, `LiquidatorStreamFeeBasicVault`, `Convex3CrvBasicVault`, `Curve3CrvBasicMetaVault` and `BasicSlippage` are all out of scope.
- [swap](./contracts/vault/swap/) contracts [BasicDexSwap](./contracts/vault/swap/BasicDexSwap.sol) and [OneInchDexSwap](./contracts/vault/swap/OneInchDexSwap.sol) are out of scope.
- [z_mocks](./contracts/z_mocks/) are just used for unit testing.
- [BasicVault](./contracts/vault/BasicVault.sol) and [LightBasicVault](./contracts/vault/LightBasicVault.sol) are out of scope.

# Mainnet Contracts

| Contract | Address|
|---|---|
|CowSwapDex | [0x8E9A9a122F402CD98727128BaF3dCCAF05189B67](https://etherscan.io/address/0x8E9A9a122F402CD98727128BaF3dCCAF05189B67) |
| Liquidator Impl | [0x56c358d4E8f9b678fc24a8Cc4aA02c02A1393fAD](https://etherscan.io/address/0x56c358d4E8f9b678fc24a8Cc4aA02c02A1393fAD) |
| Liquidator Proxy | [0xD298291059aed77686037aEfFCf497A321A4569e](https://etherscan.io/address/0xD298291059aed77686037aEfFCf497A321A4569e) |
| Curve3CrvMetapoolCalculatorLibrary | [0x5de8865522A61FC9bf2A3ca1A7D196A42863Ea56](https://etherscan.io/address/0x5de8865522A61FC9bf2A3ca1A7D196A42863Ea56) |
| Curve3CrvFactoryMetapoolCalculatorLibrary | [0x3206bf36B1e1764B4C40c5A51A8E237DC4cB10a9](https://etherscan.io/address/0x3206bf36B1e1764B4C40c5A51A8E237DC4cB10a9) |
| Curve3CrvCalculatorLibrary | [0x092C1b41163c85054F008A486BA72347B919aFa7](https://etherscan.io/address/0x092C1b41163c85054F008A486BA72347B919aFa7) |
| FRAX Convex Vault impl | [0x6DE3703418A075481c7ce01199B8e8F82C129485](https://etherscan.io/address/0x6DE3703418A075481c7ce01199B8e8F82C129485) |
| FRAX Convex Vault proxy | [0x98c5910823C2E67d54e4e0C03de44043DbfA7ca8](https://etherscan.io/address/0x98c5910823C2E67d54e4e0C03de44043DbfA7ca8) |
| mUSD Convex Vault impl | [0xa79e8e15dfd58cd5a93ed3f00bbbbe303f2a0cd8](https://etherscan.io/address/0xa79e8e15dfd58cd5a93ed3f00bbbbe303f2a0cd8) |
| mUSD Convex Vault proxy | [0xB9B47E72819934d7A5d60Bf08cD2C78072383EBb](https://etherscan.io/address/0xB9B47E72819934d7A5d60Bf08cD2C78072383EBb) |
| BUSD Convex Vault impl | [0xCd619AADd1DD2e423D1f3C725a25296c7a74281a](https://etherscan.io/address/0xCd619AADd1DD2e423D1f3C725a25296c7a74281a) |
| BUSD Convex Vault proxy | [0x87Ed92648fAE3b3930577c92c8A247b127ED8949](https://etherscan.io/address/0x87Ed92648fAE3b3930577c92c8A247b127ED8949) |
| 3Crv Meta Vault impl | [0xe3CEab97Fb4289f3A4C979E74D20c90Ab16e1F7d](https://etherscan.io/address/0xe3CEab97Fb4289f3A4C979E74D20c90Ab16e1F7d) |
| 3Crv Meta Vault proxy | [0x9614a4C61E45575b56c7e0251f63DCDe797d93C5](https://etherscan.io/address/0x9614a4C61E45575b56c7e0251f63DCDe797d93C5) |
| USDC 3CRV Convex Meta Vault impl | [0x6d68F5b8c22A549334ca85960978f9dE4DebA2D3](https://etherscan.io/address/0x6d68F5b8c22A549334ca85960978f9dE4DebA2D3) |
| USDC 3CRV Convex Meta Vault proxy | [0x455fB969dC06c4Aa77e7db3f0686CC05164436d2](https://etherscan.io/address/0x455fB969dC06c4Aa77e7db3f0686CC05164436d2) |


# Third Party Dependencies

## Contract Libraries

- [OpenZeppelin](https://www.openzeppelin.com/contracts) is used for ERC20 tokens, access control, initialization, reentry protection, proxies, casting and math operations.

## Protocols

- [Curve Finance](https://curve.fi/) used to generate yield on stablecoin deposits.
- [Convex Finance](https://www.convexfinance.com/) used to enhance the yield from Curve pools.
- [Cowswap](https://cowswap.exchange/) used for swapping Convex reward tokens (CRV and CVX) to DAI, USDC or USDT.

## Standards

- [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
- [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626)
16 changes: 1 addition & 15 deletions contracts/peripheral/Cowswap/CowSwapSeller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,6 @@ abstract contract CowSwapSeller {
uint256 toAssetAmount;
}

/// @notice Event emitted when a order is initliased.
event SwapInitiated(
bytes indexed orderUid,
address indexed fromAsset,
uint256 fromAssetAmount,
uint256 fromAssetFeeAmount
);

/// @notice Event emitted when a order is cancelled.
event SwapCancelled(bytes indexed orderUid);

Expand Down Expand Up @@ -75,17 +67,11 @@ abstract contract CowSwapSeller {
address fromAsset = orderData.fromAsset;
IERC20(fromAsset).safeIncreaseAllowance(
RELAYER,
orderData.fromAssetAmount + orderData.fromAssetFeeAmount
orderData.fromAssetAmount
);

// Once allowance is set, let's setPresignature and the order will happen
SETTLEMENT.setPreSignature(orderUid, true);
emit SwapInitiated(
orderUid,
fromAsset,
orderData.fromAssetAmount,
orderData.fromAssetFeeAmount
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
/* solhint-disable func-name-mixedcase, var-name-mixedcase */

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
/* solhint-disable func-name-mixedcase, var-name-mixedcase */

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

Expand Down
1 change: 1 addition & 0 deletions contracts/peripheral/Curve/Curve3PoolCalculatorLibrary.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
/* solhint-disable func-name-mixedcase, var-name-mixedcase */

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

Expand Down
1 change: 1 addition & 0 deletions contracts/peripheral/Curve/ICurve3Pool.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

/* solhint-disable func-name-mixedcase, var-name-mixedcase */
interface ICurve3Pool {
function A() external view returns (uint256);

Expand Down
1 change: 1 addition & 0 deletions contracts/peripheral/Curve/ICurveAddressProvider.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

/* solhint-disable func-name-mixedcase, var-name-mixedcase */
interface ICurveAddressProvider {
function get_registry() external view returns (address);

Expand Down
2 changes: 2 additions & 0 deletions contracts/peripheral/Curve/ICurveFraxBP.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.17;

/* solhint-disable func-name-mixedcase, var-name-mixedcase */

interface ICurveFraxBP {
function A() external view returns (uint256);

Expand Down
2 changes: 2 additions & 0 deletions contracts/peripheral/Curve/ICurveMetapool.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.17;

/* solhint-disable func-name-mixedcase, var-name-mixedcase */

interface ICurveMetapool {
function A() external view returns (uint256);

Expand Down
1 change: 1 addition & 0 deletions contracts/peripheral/Curve/ICurveRegistryContract.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;

/* solhint-disable func-name-mixedcase, var-name-mixedcase */
interface ICurveRegistryContract {
function find_pool_for_coins(address _from, address _to) external view returns (address);

Expand Down
33 changes: 15 additions & 18 deletions contracts/vault/swap/CowSwapDex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,26 @@ contract CowSwapDex is CowSwapSeller, ImmutableModule, IDexAsyncSwap {
*/
function _initiateSwap(DexSwapData memory swapData) internal {
// unpack the CowSwap specific params from the generic swap.data field
(bytes memory orderUid, uint256 fromAssetFeeAmount, address receiver, bool onlySign) = abi
.decode(swapData.data, (bytes, uint256, address, bool));

if (!onlySign) {
uint256 fromAssetTotalAmount = swapData.fromAssetAmount + fromAssetFeeAmount;
// transfer in the fromAsset
require(
IERC20(swapData.fromAsset).balanceOf(msg.sender) >= fromAssetTotalAmount,
"not enough from assets"
);
// Transfer rewards from the liquidator
IERC20(swapData.fromAsset).safeTransferFrom(
msg.sender,
address(this),
fromAssetTotalAmount
);
}
(bytes memory orderUid, uint256 fromAssetFeeAmount, address receiver) = abi
.decode(swapData.data, (bytes, uint256, address));

// transfer in the fromAsset
require(
IERC20(swapData.fromAsset).balanceOf(msg.sender) >= swapData.fromAssetAmount,
"not enough from assets"
);
// Transfer rewards from the liquidator
IERC20(swapData.fromAsset).safeTransferFrom(
msg.sender,
address(this),
swapData.fromAssetAmount
);

CowSwapData memory orderData = CowSwapData({
fromAsset: swapData.fromAsset,
toAsset: swapData.toAsset,
receiver: receiver,
fromAssetAmount: swapData.fromAssetAmount,
fromAssetAmount: swapData.fromAssetAmount - fromAssetFeeAmount,
fromAssetFeeAmount: fromAssetFeeAmount
});

Expand Down
Loading

0 comments on commit 4f41f30

Please sign in to comment.