diff --git a/contracts/OnChainSymmioVault.sol b/contracts/OnChainSymmioVault.sol index 5b4dda6..48e934a 100644 --- a/contracts/OnChainSymmioVault.sol +++ b/contracts/OnChainSymmioVault.sol @@ -24,6 +24,7 @@ contract OnChainSymmioVault is bytes32 public constant SETTER_ROLE = keccak256("SETTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant UNPAUSER_ROLE = keccak256("UNPAUSER_ROLE"); + uint256 public constant MIN_PAYBACK_RATIO = 0.5e18; // 50% ISymmio public symmio; address public solver; @@ -51,11 +52,6 @@ contract OnChainSymmioVault is uint256 _depositLimit, uint256 _depositPerUserLimit ) external initializer { - require( - _minimumPaybackRatio <= 1e18, - "SymmioSolverDepositor: Invalid ratio" - ); - __AccessControl_init(); __Pausable_init(); @@ -66,7 +62,7 @@ contract OnChainSymmioVault is _setLpTokenAddress(_lpTokenAddress); setDepositLimit(_depositLimit, _depositPerUserLimit); setSolver(_solver); - minimumPaybackRatio = _minimumPaybackRatio; + setMinimumPaybackRatio(_minimumPaybackRatio); _setWithdrawalPeriod(604800); } @@ -82,15 +78,11 @@ contract OnChainSymmioVault is ); IERC20 collateralToken = IERC20(collateralTokenAddress); - collateralToken.safeTransferFrom( - _msgSender(), - address(this), - amount - ); + collateralToken.safeTransferFrom(_msgSender(), address(this), amount); lpToken.mint(_msgSender(), amount); currentDeposit += amount; emit Deposit(_msgSender(), amount); - + require( collateralToken.approve(address(symmio), amount), "SymmioSolverDepositor: Approve failed" @@ -106,7 +98,7 @@ contract OnChainSymmioVault is ) external whenNotPaused { require( SymmioVaultLpToken(lpTokenAddress).balanceOf(_msgSender()) >= - amount, + amount, "SymmioSolverDepositor: Insufficient token balance" ); SymmioVaultLpToken(lpTokenAddress).burnFrom(_msgSender(), amount); @@ -183,7 +175,7 @@ contract OnChainSymmioVault is "SymmioSolverDepositor: Invalid accepted request" ); uint256 amountOut = (withdrawRequests[id].amount * _paybackRatio) / - 1e18; + 1e18; require( amountOut >= withdrawRequests[id].minAmountOut, "SymmioSolverDepositor: Payback ratio is too low for this request" @@ -192,12 +184,13 @@ contract OnChainSymmioVault is currentDeposit -= withdrawRequests[id].amount; withdrawRequests[id].status = RequestStatus.Ready; withdrawRequests[id].acceptedRatio = _paybackRatio; - withdrawRequests[id].acceptedWithdawRequestTimestamp = block.timestamp; + withdrawRequests[id].acceptedWithdawRequestTimestamp = block + .timestamp; } require( IERC20(collateralTokenAddress).balanceOf(address(this)) >= - totalRequiredBalance, + totalRequiredBalance, "SymmioSolverDepositor: Insufficient contract balance" ); lockedBalance = totalRequiredBalance; @@ -221,7 +214,9 @@ contract OnChainSymmioVault is ); require( - request.acceptedWithdawRequestTimestamp + withdrawalPeriod <= block.timestamp, "SymmioSolverDepositor: Request not pass withdrawal period" + request.acceptedWithdawRequestTimestamp + withdrawalPeriod <= + block.timestamp, + "SymmioSolverDepositor: Request not pass withdrawal period" ); request.status = RequestStatus.Done; @@ -243,13 +238,15 @@ contract OnChainSymmioVault is _updateCollateral(); require( beforeCollateral == collateralTokenAddress || - beforeCollateral == address(0), + beforeCollateral == address(0), "SymmioSolverDepositor: Collateral can not be changed" ); emit SymmioAddressUpdatedEvent(_symmioAddress); } - - function setWithdrawalPeriod(uint256 withdrawalPeriod_) public onlyRole(SETTER_ROLE) { + + function setWithdrawalPeriod( + uint256 withdrawalPeriod_ + ) public onlyRole(SETTER_ROLE) { _setWithdrawalPeriod(withdrawalPeriod_); } @@ -268,6 +265,21 @@ contract OnChainSymmioVault is emit DepositLimitUpdatedEvent(_depositLimit, _depositPerUserLimit); } + function setMinimumPaybackRatio( + uint256 _minimumPaybackRatio + ) public onlyRole(SETTER_ROLE) { + require( + _minimumPaybackRatio >= MIN_PAYBACK_RATIO, + "SymmioSolverDepositor: Minimum buyback ratio is too low" + ); + require( + _minimumPaybackRatio <= 1e18, + "SymmioSolverDepositor: Minimum buyback ratio is too high" + ); + minimumPaybackRatio = _minimumPaybackRatio; + emit MinimumPaybackRatioUpdatedEvent(_minimumPaybackRatio); + } + function pause() external onlyRole(PAUSER_ROLE) { _pause(); } diff --git a/contracts/interfaces/IOnChainSymmioVault.sol b/contracts/interfaces/IOnChainSymmioVault.sol index c71433a..dccb575 100644 --- a/contracts/interfaces/IOnChainSymmioVault.sol +++ b/contracts/interfaces/IOnChainSymmioVault.sol @@ -20,7 +20,7 @@ interface IOnChainSymmioVault { } event WithdrawalPeriodUpdate(uint256 withdrawalPeriod); - + event Deposit(address indexed depositor, uint256 amount); event WithdrawRequestEvent( uint256 indexed requestId, @@ -39,12 +39,15 @@ interface IOnChainSymmioVault { address indexed receiver ); event SymmioAddressUpdatedEvent(address indexed newSymmioAddress); - event DepositLimitUpdatedEvent(uint256 depositLimit, uint256 depositPerUserLimit); - + event DepositLimitUpdatedEvent( + uint256 depositLimit, + uint256 depositPerUserLimit + ); + event MinimumPaybackRatioUpdatedEvent(uint256 minimumPaybackRatio); event SolverUpdatedEvent(address indexed solver); event DepositToSymmio( address indexed depositor, address indexed solver, uint256 amount ); -} \ No newline at end of file +} diff --git a/hardhat.config.ts b/hardhat.config.ts index 1d99f9c..fc5a363 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,69 +1,76 @@ -import { HardhatUserConfig } from "hardhat/config" -import "@nomicfoundation/hardhat-toolbox" -import "@openzeppelin/hardhat-upgrades" -import { resolve } from "path" +import { HardhatUserConfig } from "hardhat/config"; +import "@nomicfoundation/hardhat-toolbox"; +import "@openzeppelin/hardhat-upgrades"; +import { ethers } from "ethers"; +import { resolve } from "path"; -import { config as dotenvConfig } from "dotenv" +import { config as dotenvConfig } from "dotenv"; -const dotenvConfigPath: string = process.env.DOTENV_CONFIG_PATH || "./.env" -dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }) +const dotenvConfigPath: string = process.env.DOTENV_CONFIG_PATH || "./.env"; +dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }); // Ensure that we have all the environment variables we need. -const privateKey: string | undefined = process.env.PRIVATE_KEY -if (!privateKey) - throw new Error("Please set your PRIVATE_KEY in a .env file") - -const baseApiKey: string = process.env.BASE_API_KEY || "" +const privateKey: string | undefined = process.env.PRIVATE_KEY; +if (!privateKey) throw new Error("Please set your PRIVATE_KEY in a .env file"); +const wallet = new ethers.Wallet(privateKey); +if (wallet.address !== "0xf1d63df1CD64a3f3A8F440bAba619dbB4baBB020") + console.warn( + `Using wallet ${wallet.address} instead of original 0xf1d63df1CD64a3f3A8F440bAba619dbB4baBB020` + ); +const baseApiKey: string = process.env.BASE_API_KEY || ""; const config: HardhatUserConfig = { - defaultNetwork: "hardhat", - gasReporter: { - currency: "USD", - enabled: true, - excludeContracts: [], - src: "./contracts", - }, - networks: { - hardhat: { - allowUnlimitedContractSize: false, - }, - base: { - url: "https://1rpc.io/base", - accounts: [privateKey || `0x0`], - }, }, - etherscan: { - apiKey: { - base: baseApiKey, - }, - customChains: [ - { - network: "base", - chainId: 8453, - urls: { - apiURL: `https://api.basescan.org/api?apiKey=${baseApiKey}`, - browserURL: "https://basescan.org", - }, - }, ], - }, - paths: { - artifacts: "./artifacts", - cache: "./cache", - sources: "./contracts", - tests: "./test", - }, - solidity: { - version: "0.8.28", - settings: { - metadata: { - bytecodeHash: "none", - }, - optimizer: { - enabled: true, - runs: 200000, - }, - viaIR: true, - }, - }, -} + defaultNetwork: "hardhat", + gasReporter: { + currency: "USD", + enabled: true, + excludeContracts: [], + src: "./contracts", + }, + networks: { + hardhat: { + allowUnlimitedContractSize: false, + }, + base: { + url: "https://1rpc.io/base", + accounts: [privateKey || `0x0`], + }, + }, + etherscan: { + apiKey: { + base: baseApiKey, + }, + customChains: [ + { + network: "base", + chainId: 8453, + urls: { + apiURL: `https://api.basescan.org/api?apiKey=${baseApiKey}`, + browserURL: "https://basescan.org", + }, + }, + ], + }, + paths: { + artifacts: "./artifacts", + cache: "./cache", + sources: "./contracts", + tests: "./test", + }, + solidity: { + version: "0.8.28", + settings: { + evmVersion: "cancun", + metadata: { + bytecodeHash: "none", + }, + optimizer: { + enabled: true, + runs: 200000, + }, + viaIR: true, + }, + }, +}; export default config;