Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
4 changes: 4 additions & 0 deletions .github/workflows/certora-prover.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ jobs:
with:
submodules: recursive

# Install foundry, needed for prover path resolution
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

# Run Certora munge script
- name: Certora munge
run: ./certora/scripts/patch.sh
Expand Down
20 changes: 12 additions & 8 deletions certora/confs/BaseConfForInheritance.conf
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@
"VaultMock1:_asset=Token0",
"EulerEarnHarness:_asset=Token0"
],
"packages": [
"ethereum-vault-connector=lib/ethereum-vault-connector/src",
"euler-vault-kit=lib/euler-vault-kit/src",
"forge-std=lib/forge-std/src",
"solmate=lib/euler-vault-kit/lib/permit2/lib/solmate"
],
"compiler_map": {
"EulerEarnHarness": "solc-0.8.26",
"EthereumVaultConnector": "solc-0.8.26",
Expand All @@ -42,8 +36,18 @@
"ERC20Helper": "solc-0.8.26"
},
"solc_optimize": "200",
"solc_via_ir": true,
"assert_autofinder_success": true,
"solc_via_ir_map": {
"ERC20Helper": false,
"EthereumVaultConnector": false,
"EulerEarnFactory": false,
"EulerEarnHarness": false,
"IRMLinearKink": false,
"Permit2": true,
"PerspectiveMock": false,
"Token0": false,
"VaultMock0": false,
"VaultMock1": false
},
"contract_recursion_limit": "1",
"process": "emv",
"prover_args": [
Expand Down
2 changes: 1 addition & 1 deletion certora/harnesses/ERC20Helper.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import {SafeERC20, IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

contract ERC20Helper {
using SafeERC20 for IERC20;
Expand Down
2 changes: 1 addition & 1 deletion certora/mocks/Token0.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.21;

import {ERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {ERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol";

contract Token0 is ERC20 {
constructor() ERC20("Token0", "TOK0") {}
Expand Down
2 changes: 1 addition & 1 deletion certora/mocks/VaultMock0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
ERC20,
ERC4626,
Math
} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol";
} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol";

contract VaultMock0 is ERC4626 {
constructor(IERC20 asset) ERC4626(asset) ERC20("VaultMock0", "V0") {}
Expand Down
2 changes: 1 addition & 1 deletion certora/mocks/VaultMock1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
ERC20,
ERC4626,
Math
} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol";
} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol";

contract VaultMock1 is ERC4626 {
constructor(IERC20 asset) ERC4626(asset) ERC20("VaultMock1", "V1") {}
Expand Down
23 changes: 11 additions & 12 deletions certora/scripts/EulerEarn.patch
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol
index 4635a89..ae0869b 100644
index 27c1873..1efc278 100644
--- a/src/EulerEarn.sol
+++ b/src/EulerEarn.sol
@@ -106,6 +106,18 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -106,6 +106,17 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
/// @dev "Overrides" the ERC20's storage variable to be able to modify it.
string private _symbol;

Expand All @@ -14,14 +14,13 @@ index 4635a89..ae0869b 100644
+ // The last index at which a market identifier has been removed from the withdraw queue.
+ mapping(address => uint256) public deletedAt;
+
+ // hooks for cvl assertions
+ function HOOK_after_accrueInterest() internal {}
+ function HOOK_after_withdrawStrategy(uint256) internal {}
+
/* CONSTRUCTOR */

/// @dev Initializes the contract.
@@ -353,6 +365,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -353,6 +364,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
seen[prevIndex] = true;

newWithdrawQueue[i] = id;
Expand All @@ -31,7 +30,7 @@ index 4635a89..ae0869b 100644
}

for (uint256 i; i < currLength; ++i) {
@@ -369,6 +384,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -369,6 +383,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
revert ErrorsLib.InvalidMarketRemovalTimelockNotElapsed(id);
}
}
Expand All @@ -41,39 +40,39 @@ index 4635a89..ae0869b 100644

delete config[id];
}
@@ -559,6 +577,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -559,6 +576,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
/// @inheritdoc IERC4626
function deposit(uint256 assets, address receiver) public override nonReentrant returns (uint256 shares) {
_accrueInterest();
+ HOOK_after_accrueInterest();

shares = _convertToSharesWithTotals(assets, totalSupply(), lastTotalAssets, Math.Rounding.Floor);

@@ -570,6 +589,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -570,6 +588,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
/// @inheritdoc IERC4626
function mint(uint256 shares, address receiver) public override nonReentrant returns (uint256 assets) {
_accrueInterest();
+ HOOK_after_accrueInterest();

assets = _convertToAssetsWithTotals(shares, totalSupply(), lastTotalAssets, Math.Rounding.Ceil);

@@ -584,6 +604,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -584,6 +603,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
returns (uint256 shares)
{
_accrueInterest();
+ HOOK_after_accrueInterest();

// Do not call expensive `maxWithdraw` and optimistically withdraw assets.

@@ -600,6 +621,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -600,6 +620,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
returns (uint256 assets)
{
_accrueInterest();
+ HOOK_after_accrueInterest();

// Do not call expensive `maxRedeem` and optimistically redeem shares.

@@ -729,7 +751,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -729,7 +750,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
// clamp at 0 so the error raised is the more informative NotEnoughLiquidity.
_updateLastTotalAssets(lastTotalAssets.zeroFloorSub(assets));

Expand All @@ -83,7 +82,7 @@ index 4635a89..ae0869b 100644

super._withdraw(caller, receiver, owner, assets, shares);
}
@@ -780,6 +804,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -780,6 +803,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
IERC20(asset()).forceApproveMaxWithPermit2(address(id), permit2);

if (!marketConfig.enabled) {
Expand All @@ -93,7 +92,7 @@ index 4635a89..ae0869b 100644
withdrawQueue.push(id);

if (withdrawQueue.length > ConstantsLib.MAX_QUEUE_LENGTH) revert ErrorsLib.MaxQueueLengthExceeded();
@@ -837,6 +864,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
@@ -837,6 +863,9 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar
/// @dev Withdraws `assets` from the strategy vaults.
function _withdrawStrategy(uint256 assets) internal {
for (uint256 i; i < withdrawQueue.length; ++i) {
Expand Down
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/
ethereum-vault-connector/=lib/ethereum-vault-connector/src/
14 changes: 7 additions & 7 deletions src/EulerEarn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol";
import {EventsLib} from "./libraries/EventsLib.sol";
import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol";
import {UtilsLib, WAD} from "./libraries/UtilsLib.sol";
import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol";
import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol";
import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol";

import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol";
import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol";
import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import {Context} from "openzeppelin-contracts/utils/Context.sol";
import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol";
import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol";
import {
IERC20,
IERC4626,
ERC20,
ERC4626,
Math,
SafeERC20
} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol";
import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol";
} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol";
import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol";

/// @title EulerEarn
/// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs.
Expand Down
4 changes: 2 additions & 2 deletions src/EulerEarnFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol";

import {EulerEarn} from "./EulerEarn.sol";

import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol";
import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol";
import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol";
import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol";

/// @title EulerEarnFactory
/// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs.
Expand Down
4 changes: 2 additions & 2 deletions src/PublicAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol";
import {ErrorsLib} from "./libraries/ErrorsLib.sol";
import {EventsLib} from "./libraries/EventsLib.sol";

import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";
import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol";

/// @title PublicAllocator
/// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs.
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/IEulerEarn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity >=0.5.0;

import {IEulerEarnFactory} from "./IEulerEarnFactory.sol";

import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol";

import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IPublicAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity >=0.5.0;

import {MarketAllocation} from "./IEulerEarn.sol";

import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";

/// @dev Max settable flow cap, such that caps can always be stored on 128 bits.
/// @dev The actual max possible flow cap is type(uint128).max-1.
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/ErrorsLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";

/// @title ErrorsLib
/// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs.
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/EventsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.0;

import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol";

import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";

import {PendingAddress} from "./PendingLib.sol";

Expand Down
4 changes: 2 additions & 2 deletions src/libraries/SafeERC20Permit2Lib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
pragma solidity ^0.8.0;

import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol";
import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

/// @title SafeERC20Permit2Lib Library
/// @custom:security-contact [email protected]
Expand Down
2 changes: 1 addition & 1 deletion test/ERC4626Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ contract ERC4626Test is IntegrationTest {

// max deposit is 0
assertEq(vault.maxDeposit(SUPPLIER), 0);
// although cap still allows 1 wei
// although cap still allows 1 wei
assertEq(vault.totalAssets(), cap - 1);
// because depositing 1 wei would throw zero shares
vm.prank(SUPPLIER);
Expand Down
Loading