Skip to content

Commit

Permalink
invoke swap router for eth swap
Browse files Browse the repository at this point in the history
  • Loading branch information
ewansheldon committed Oct 9, 2023
1 parent 128cadd commit b699f2a
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 45 deletions.
58 changes: 42 additions & 16 deletions contracts/SmartVaultV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import "contracts/interfaces/IEUROs.sol";
import "contracts/interfaces/IPriceCalculator.sol";
import "contracts/interfaces/ISmartVault.sol";
import "contracts/interfaces/ISmartVaultManager.sol";
import "contracts/interfaces/ISmartVaultManagerV2.sol";
import "contracts/interfaces/ISwapRouter.sol";
import "contracts/interfaces/ITokenManager.sol";

contract SmartVaultV2 is ISmartVault {
Expand All @@ -17,7 +19,7 @@ contract SmartVaultV2 is ISmartVault {
uint8 private constant version = 2;
bytes32 private constant vaultType = bytes32("EUROs");
bytes32 private immutable NATIVE;
ISmartVaultManager public immutable manager;
address public immutable manager;
IEUROs public immutable EUROs;
IPriceCalculator public immutable calculator;

Expand All @@ -33,13 +35,13 @@ contract SmartVaultV2 is ISmartVault {
constructor(bytes32 _native, address _manager, address _owner, address _euros, address _priceCalculator) {
NATIVE = _native;
owner = _owner;
manager = ISmartVaultManager(_manager);
manager = _manager;
EUROs = IEUROs(_euros);
calculator = IPriceCalculator(_priceCalculator);
}

modifier onlyVaultManager {
require(msg.sender == address(manager), INVALID_USER);
require(msg.sender == manager, INVALID_USER);
_;
}

Expand All @@ -59,11 +61,11 @@ contract SmartVaultV2 is ISmartVault {
}

function getTokenManager() private view returns (ITokenManager) {
return ITokenManager(manager.tokenManager());
return ITokenManager(ISmartVaultManager(manager).tokenManager());
}

function euroCollateral() private view returns (uint256 euros) {
ITokenManager tokenManager = ITokenManager(manager.tokenManager());
ITokenManager tokenManager = ITokenManager(ISmartVaultManager(manager).tokenManager());
ITokenManager.Token[] memory acceptedTokens = tokenManager.getAcceptedTokens();
for (uint256 i = 0; i < acceptedTokens.length; i++) {
ITokenManager.Token memory token = acceptedTokens[i];
Expand All @@ -72,15 +74,15 @@ contract SmartVaultV2 is ISmartVault {
}

function maxMintable() private view returns (uint256) {
return euroCollateral() * manager.HUNDRED_PC() / manager.collateralRate();
return euroCollateral() * ISmartVaultManager(manager).HUNDRED_PC() / ISmartVaultManager(manager).collateralRate();
}

function getAssetBalance(bytes32 _symbol, address _tokenAddress) private view returns (uint256 amount) {
return _symbol == NATIVE ? address(this).balance : IERC20(_tokenAddress).balanceOf(address(this));
}

function getAssets() private view returns (Asset[] memory) {
ITokenManager tokenManager = ITokenManager(manager.tokenManager());
ITokenManager tokenManager = ITokenManager(ISmartVaultManager(manager).tokenManager());
ITokenManager.Token[] memory acceptedTokens = tokenManager.getAcceptedTokens();
Asset[] memory assets = new Asset[](acceptedTokens.length);
for (uint256 i = 0; i < acceptedTokens.length; i++) {
Expand All @@ -104,21 +106,21 @@ contract SmartVaultV2 is ISmartVault {

function liquidateNative() private {
if (address(this).balance != 0) {
(bool sent,) = payable(manager.protocol()).call{value: address(this).balance}("");
(bool sent,) = payable(ISmartVaultManager(manager).protocol()).call{value: address(this).balance}("");
require(sent, "err-native-liquidate");
}
}

function liquidateERC20(IERC20 _token) private {
if (_token.balanceOf(address(this)) != 0) _token.safeTransfer(manager.protocol(), _token.balanceOf(address(this)));
if (_token.balanceOf(address(this)) != 0) _token.safeTransfer(ISmartVaultManager(manager).protocol(), _token.balanceOf(address(this)));
}

function liquidate() external onlyVaultManager {
require(undercollateralised(), "err-not-liquidatable");
liquidated = true;
minted = 0;
liquidateNative();
ITokenManager.Token[] memory tokens = ITokenManager(manager.tokenManager()).getAcceptedTokens();
ITokenManager.Token[] memory tokens = ITokenManager(ISmartVaultManager(manager).tokenManager()).getAcceptedTokens();
for (uint256 i = 0; i < tokens.length; i++) {
if (tokens[i].symbol != NATIVE) liquidateERC20(IERC20(tokens[i].addr));
}
Expand Down Expand Up @@ -160,24 +162,48 @@ contract SmartVaultV2 is ISmartVault {
}

function mint(address _to, uint256 _amount) external onlyOwner ifNotLiquidated {
uint256 fee = _amount * manager.mintFeeRate() / manager.HUNDRED_PC();
uint256 fee = _amount * ISmartVaultManager(manager).mintFeeRate() / ISmartVaultManager(manager).HUNDRED_PC();
require(fullyCollateralised(_amount + fee), UNDER_COLL);
minted = minted + _amount + fee;
EUROs.mint(_to, _amount);
EUROs.mint(manager.protocol(), fee);
EUROs.mint(ISmartVaultManager(manager).protocol(), fee);
emit EUROsMinted(_to, _amount, fee);
}

function burn(uint256 _amount) external ifMinted(_amount) {
uint256 fee = _amount * manager.burnFeeRate() / manager.HUNDRED_PC();
uint256 fee = _amount * ISmartVaultManager(manager).burnFeeRate() / ISmartVaultManager(manager).HUNDRED_PC();
minted = minted - _amount;
EUROs.burn(msg.sender, _amount);
IERC20(address(EUROs)).safeTransferFrom(msg.sender, manager.protocol(), fee);
IERC20(address(EUROs)).safeTransferFrom(msg.sender, ISmartVaultManager(manager).protocol(), fee);
emit EUROsBurned(_amount, fee);
}

function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount, uint256 _minAmount) external {

function getSwapAddressFor(bytes32 _symbol) private view returns (address swapAddress) {
bool validToken;
ITokenManager.Token[] memory tokens = ITokenManager(ISmartVaultManager(manager).tokenManager()).getAcceptedTokens();
for (uint256 i = 0; i < tokens.length; i++) {
if (tokens[i].symbol == _symbol) {
validToken = true;
swapAddress = tokens[i].addr;
}
}
require(validToken, "err-invalid-swap");
if (swapAddress == address(0)) swapAddress = ISmartVaultManagerV2(manager).weth();
}

function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external {
ISwapRouter(ISmartVaultManagerV2(manager).swapRouter()).exactInputSingle{value: _amount}(
ISwapRouter.ExactInputSingleParams({
tokenIn: getSwapAddressFor(_inToken),
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
);
}

function setOwner(address _newOwner) external onlyVaultManager {
Expand Down
7 changes: 7 additions & 0 deletions contracts/interfaces/ISmartVaultManagerV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

interface ISmartVaultManagerV2 {
function weth() external view returns (address);
function swapRouter() external view returns (address);
}
17 changes: 17 additions & 0 deletions contracts/interfaces/ISwapRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}

function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
}
37 changes: 36 additions & 1 deletion contracts/test_utils/MockSwapRouter.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

contract MockSwapRouter {
import "contracts/interfaces/ISwapRouter.sol";

contract MockSwapRouter is ISwapRouter {
address private tokenIn;
address private tokenOut;
uint24 private fee;
address private recipient;
uint256 private deadline;
uint256 private amountIn;
uint256 private amountOutMinimum;
uint160 private sqrtPriceLimitX96;
uint256 private txValue;

struct MockSwapData {
address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline;
uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; uint256 txValue;
}

function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut) {
tokenIn = params.tokenIn;
tokenOut = params.tokenOut;
fee = params.fee;
recipient = params.recipient;
deadline = params.deadline;
amountIn = params.amountIn;
amountOutMinimum = params.amountOutMinimum;
sqrtPriceLimitX96 = params.sqrtPriceLimitX96;
txValue = msg.value;
}

function receivedSwap() external view returns (MockSwapData memory) {
return MockSwapData(
tokenIn, tokenOut, fee, recipient, deadline, amountIn, amountOutMinimum,
sqrtPriceLimitX96, txValue
);
}
}
10 changes: 10 additions & 0 deletions contracts/versions/SmartVaultManagerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ contract SmartVaultManagerV2 is ISmartVaultManager, Initializable, ERC721Upgrade
address public nftMetadataGenerator;
uint256 public mintFeeRate;
uint256 public burnFeeRate;
address public weth;
address public swapRouter;

event VaultDeployed(address indexed vaultAddress, address indexed owner, address vaultType, uint256 tokenId);
event VaultLiquidated(address indexed vaultAddress);
Expand Down Expand Up @@ -110,6 +112,14 @@ contract SmartVaultManagerV2 is ISmartVaultManager, Initializable, ERC721Upgrade
burnFeeRate = _rate;
}

function setWethAddress(address _weth) external onlyOwner() {
weth = _weth;
}

function setSwapRouterAddress(address _swapRouter) external onlyOwner() {
swapRouter = _swapRouter;
}

function setNFTMetadataGenerator(address _nftMetadataGenerator) external onlyOwner() {
nftMetadataGenerator = _nftMetadataGenerator;
}
Expand Down
101 changes: 101 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@openzeppelin/contracts": "^4.8.0",
"@openzeppelin/contracts-upgradeable": "^4.8.2",
"@openzeppelin/hardhat-upgrades": "^1.22.1",
"@uniswap/v3-periphery": "^1.4.4",
"dotenv": "^16.0.3",
"hardhat": "^2.12.4",
"hardhat-contract-sizer": "^2.6.1",
Expand Down
Loading

0 comments on commit b699f2a

Please sign in to comment.