diff --git a/certora/Makefile b/certora/Makefile index bbbddbcab..6ef6b2bf6 100644 --- a/certora/Makefile +++ b/certora/Makefile @@ -21,4 +21,3 @@ record: clean: git clean -fdX touch $(PATCH) - diff --git a/certora/applyHarness.patch b/certora/applyHarness.patch index e339df7c3..90967d1b0 100644 --- a/certora/applyHarness.patch +++ b/certora/applyHarness.patch @@ -1,12 +1,6 @@ -diff -ruN .gitignore .gitignore ---- .gitignore 1969-12-31 16:00:00.000000000 -0800 -+++ .gitignore 2022-08-11 21:28:36.000000000 -0700 -@@ -0,0 +1,2 @@ -+* -+!.gitignore diff -ruN access/AccessControl.sol access/AccessControl.sol ---- access/AccessControl.sol 2022-08-11 21:28:00.000000000 -0700 -+++ access/AccessControl.sol 2022-08-11 21:28:36.000000000 -0700 +--- access/AccessControl.sol 2022-09-20 11:01:10.429515094 +0200 ++++ access/AccessControl.sol 2022-09-20 14:34:08.629602185 +0200 @@ -93,7 +93,7 @@ * * _Available since v4.6._ @@ -17,8 +11,8 @@ diff -ruN access/AccessControl.sol access/AccessControl.sol } diff -ruN access/Ownable.sol access/Ownable.sol ---- access/Ownable.sol 2022-08-11 21:28:00.000000000 -0700 -+++ access/Ownable.sol 2022-08-11 21:28:36.000000000 -0700 +--- access/Ownable.sol 2022-09-09 10:15:55.887175731 +0200 ++++ access/Ownable.sol 2022-09-20 14:34:08.629602185 +0200 @@ -30,14 +30,6 @@ } @@ -48,9 +42,41 @@ diff -ruN access/Ownable.sol access/Ownable.sol } /** +diff -ruN .gitignore .gitignore +--- .gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ .gitignore 2022-09-20 14:34:08.626268788 +0200 +@@ -0,0 +1,2 @@ ++* ++!.gitignore +diff -ruN governance/extensions/GovernorCountingSimple.sol governance/extensions/GovernorCountingSimple.sol +--- governance/extensions/GovernorCountingSimple.sol 2022-09-20 11:01:10.432848512 +0200 ++++ governance/extensions/GovernorCountingSimple.sol 2022-09-20 14:34:08.632935582 +0200 +@@ -27,7 +27,7 @@ + mapping(address => bool) hasVoted; + } + +- mapping(uint256 => ProposalVote) private _proposalVotes; ++ mapping(uint256 => ProposalVote) internal _proposalVotes; + + /** + * @dev See {IGovernor-COUNTING_MODE}. +diff -ruN governance/extensions/GovernorPreventLateQuorum.sol governance/extensions/GovernorPreventLateQuorum.sol +--- governance/extensions/GovernorPreventLateQuorum.sol 2022-08-31 13:44:36.377724869 +0200 ++++ governance/extensions/GovernorPreventLateQuorum.sol 2022-09-20 14:34:08.632935582 +0200 +@@ -21,8 +21,8 @@ + using SafeCast for uint256; + using Timers for Timers.BlockNumber; + +- uint64 private _voteExtension; +- mapping(uint256 => Timers.BlockNumber) private _extendedDeadlines; ++ uint64 internal _voteExtension; // PRIVATE => INTERNAL ++ mapping(uint256 => Timers.BlockNumber) internal _extendedDeadlines; // PRIVATE => INTERNAL + + /// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period. + event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline); diff -ruN governance/Governor.sol governance/Governor.sol ---- governance/Governor.sol 2022-08-11 21:28:00.000000000 -0700 -+++ governance/Governor.sol 2022-08-11 21:28:36.000000000 -0700 +--- governance/Governor.sol 2022-09-20 11:01:10.429515094 +0200 ++++ governance/Governor.sol 2022-09-20 14:34:08.629602185 +0200 @@ -44,7 +44,7 @@ string private _name; @@ -61,8 +87,8 @@ diff -ruN governance/Governor.sol governance/Governor.sol // This queue keeps track of the governor operating on itself. Calls to functions protected by the // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute}, diff -ruN governance/TimelockController.sol governance/TimelockController.sol ---- governance/TimelockController.sol 2022-08-11 21:28:00.000000000 -0700 -+++ governance/TimelockController.sol 2022-08-11 21:28:36.000000000 -0700 +--- governance/TimelockController.sol 2022-09-09 10:15:55.887175731 +0200 ++++ governance/TimelockController.sol 2022-09-20 14:34:08.629602185 +0200 @@ -28,10 +28,10 @@ bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); @@ -76,35 +102,9 @@ diff -ruN governance/TimelockController.sol governance/TimelockController.sol /** * @dev Emitted when a call is scheduled as part of operation `id`. -diff -ruN governance/extensions/GovernorCountingSimple.sol governance/extensions/GovernorCountingSimple.sol ---- governance/extensions/GovernorCountingSimple.sol 2022-08-11 21:28:00.000000000 -0700 -+++ governance/extensions/GovernorCountingSimple.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -27,7 +27,7 @@ - mapping(address => bool) hasVoted; - } - -- mapping(uint256 => ProposalVote) private _proposalVotes; -+ mapping(uint256 => ProposalVote) internal _proposalVotes; - - /** - * @dev See {IGovernor-COUNTING_MODE}. -diff -ruN governance/extensions/GovernorPreventLateQuorum.sol governance/extensions/GovernorPreventLateQuorum.sol ---- governance/extensions/GovernorPreventLateQuorum.sol 2022-08-11 21:28:00.000000000 -0700 -+++ governance/extensions/GovernorPreventLateQuorum.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -21,8 +21,8 @@ - using SafeCast for uint256; - using Timers for Timers.BlockNumber; - -- uint64 private _voteExtension; -- mapping(uint256 => Timers.BlockNumber) private _extendedDeadlines; -+ uint64 internal _voteExtension; // PRIVATE => INTERNAL -+ mapping(uint256 => Timers.BlockNumber) internal _extendedDeadlines; // PRIVATE => INTERNAL - - /// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period. - event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline); diff -ruN governance/utils/Votes.sol governance/utils/Votes.sol ---- governance/utils/Votes.sol 2022-08-11 21:28:00.000000000 -0700 -+++ governance/utils/Votes.sol 2022-08-11 21:28:36.000000000 -0700 +--- governance/utils/Votes.sol 2022-09-20 14:24:58.010074267 +0200 ++++ governance/utils/Votes.sol 2022-09-20 14:34:08.632935582 +0200 @@ -35,7 +35,25 @@ bytes32 private constant _DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); @@ -178,8 +178,8 @@ diff -ruN governance/utils/Votes.sol governance/utils/Votes.sol + function _getVotingUnits(address) public virtual returns (uint256); // HARNESS: internal -> public } diff -ruN metatx/MinimalForwarder.sol metatx/MinimalForwarder.sol ---- metatx/MinimalForwarder.sol 2022-08-11 21:28:00.000000000 -0700 -+++ metatx/MinimalForwarder.sol 2022-08-11 21:28:36.000000000 -0700 +--- metatx/MinimalForwarder.sol 2022-09-20 11:16:48.456850883 +0200 ++++ metatx/MinimalForwarder.sol 2022-09-20 14:34:08.632935582 +0200 @@ -8,11 +8,6 @@ /** @@ -193,8 +193,8 @@ diff -ruN metatx/MinimalForwarder.sol metatx/MinimalForwarder.sol contract MinimalForwarder is EIP712 { using ECDSA for bytes32; diff -ruN mocks/ERC20TokenizedVaultMock.sol mocks/ERC20TokenizedVaultMock.sol ---- mocks/ERC20TokenizedVaultMock.sol 1969-12-31 16:00:00.000000000 -0800 -+++ mocks/ERC20TokenizedVaultMock.sol 2022-08-11 21:28:36.000000000 -0700 +--- mocks/ERC20TokenizedVaultMock.sol 1970-01-01 01:00:00.000000000 +0100 ++++ mocks/ERC20TokenizedVaultMock.sol 2022-09-20 14:34:08.632935582 +0200 @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT + @@ -218,47 +218,21 @@ diff -ruN mocks/ERC20TokenizedVaultMock.sol mocks/ERC20TokenizedVaultMock.sol + _burn(account, amount); + } +} -diff -ruN mocks/ERC4626Mock.sol mocks/ERC4626Mock.sol ---- mocks/ERC4626Mock.sol 2022-08-11 21:28:00.000000000 -0700 -+++ mocks/ERC4626Mock.sol 1969-12-31 16:00:00.000000000 -0800 -@@ -1,22 +0,0 @@ --// SPDX-License-Identifier: MIT -- --pragma solidity ^0.8.0; -- --import "../token/ERC20/extensions/ERC4626.sol"; -- --// mock class using ERC20 --contract ERC4626Mock is ERC4626 { -- constructor( -- IERC20Metadata asset, -- string memory name, -- string memory symbol -- ) ERC20(name, symbol) ERC4626(asset) {} -- -- function mockMint(address account, uint256 amount) public { -- _mint(account, amount); -- } -- -- function mockBurn(address account, uint256 amount) public { -- _burn(account, amount); -- } --} diff -ruN mocks/MathMock.sol mocks/MathMock.sol ---- mocks/MathMock.sol 2022-08-11 21:28:00.000000000 -0700 -+++ mocks/MathMock.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -29,8 +29,4 @@ - ) public pure returns (uint256) { - return Math.mulDiv(a, b, denominator, direction); +--- mocks/MathMock.sol 2022-09-20 14:24:58.013407601 +0200 ++++ mocks/MathMock.sol 2022-09-20 14:34:24.803248911 +0200 +@@ -45,4 +45,8 @@ + function log256(uint256 a, Math.Rounding direction) public pure returns (uint256) { + return Math.log256(a, direction); } -- -- function sqrt(uint256 a, Math.Rounding direction) public pure returns (uint256) { -- return Math.sqrt(a, direction); -- } ++ ++ function sqrt(uint256 a, Math.Rounding direction) public pure returns (uint256) { ++ return Math.sqrt(a, direction); ++ } } diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol ---- mocks/SafeERC20Helper.sol 2022-08-11 21:28:00.000000000 -0700 -+++ mocks/SafeERC20Helper.sol 2022-08-11 21:28:36.000000000 -0700 +--- mocks/SafeERC20Helper.sol 2022-09-20 14:24:58.013407601 +0200 ++++ mocks/SafeERC20Helper.sol 2022-09-20 15:09:17.135329080 +0200 @@ -4,7 +4,6 @@ import "../utils/Context.sol"; @@ -267,7 +241,7 @@ diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol import "../token/ERC20/utils/SafeERC20.sol"; contract ERC20ReturnFalseMock is Context { -@@ -106,43 +105,6 @@ +@@ -106,42 +105,43 @@ } } @@ -287,7 +261,7 @@ diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol - uint8 v, - bytes32 r, - bytes32 s -- ) public virtual { +- ) public { - super.permit(owner, spender, value, deadline, v, r, s); - } - @@ -299,7 +273,7 @@ diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol - uint8 v, - bytes32 r, - bytes32 s -- ) public virtual override { +- ) public override { - try this.permitThatMayRevert(owner, spender, value, deadline, v, r, s) { - // do nothing - } catch { @@ -307,11 +281,47 @@ diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol - } - } -} -- ++// Harness remove ? ++// contract ERC20PermitNoRevertMock is ++// ERC20("ERC20PermitNoRevertMock", "ERC20PermitNoRevertMock"), ++// ERC20Permit("ERC20PermitNoRevertMock") ++// { ++// function getChainId() external view returns (uint256) { ++// return block.chainid; ++// } ++ ++// function permitThatMayRevert( ++// address owner, ++// address spender, ++// uint256 value, ++// uint256 deadline, ++// uint8 v, ++// bytes32 r, ++// bytes32 s ++// ) public { ++// super.permit(owner, spender, value, deadline, v, r, s); ++// } ++ ++// function permit( ++// address owner, ++// address spender, ++// uint256 value, ++// uint256 deadline, ++// uint8 v, ++// bytes32 r, ++// bytes32 s ++// ) public override { ++// try this.permitThatMayRevert(owner, spender, value, deadline, v, r, s) { ++// // do nothing ++// } catch { ++// // do nothing ++// } ++// } ++// } + contract SafeERC20Wrapper is Context { using SafeERC20 for IERC20; - -@@ -172,18 +134,6 @@ +@@ -172,18 +172,6 @@ _token.safeDecreaseAllowance(address(0), amount); } @@ -330,74 +340,9 @@ diff -ruN mocks/SafeERC20Helper.sol mocks/SafeERC20Helper.sol function setAllowance(uint256 allowance_) public { ERC20ReturnTrueMock(address(_token)).setAllowance(allowance_); } -diff -ruN proxy/Clones.sol proxy/Clones.sol ---- proxy/Clones.sol 2022-08-11 21:28:00.000000000 -0700 -+++ proxy/Clones.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -26,10 +26,10 @@ - /// @solidity memory-safe-assembly - assembly { - let ptr := mload(0x40) -- mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) -- mstore(add(ptr, 0x14), shl(0x60, implementation)) -- mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) -- instance := create(0, ptr, 0x37) -+ mstore(ptr, 0x602d8060093d393df3363d3d373d3d3d363d7300000000000000000000000000) -+ mstore(add(ptr, 0x13), shl(0x60, implementation)) -+ mstore(add(ptr, 0x27), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) -+ instance := create(0, ptr, 0x36) - } - require(instance != address(0), "ERC1167: create failed"); - } -@@ -45,10 +45,10 @@ - /// @solidity memory-safe-assembly - assembly { - let ptr := mload(0x40) -- mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) -- mstore(add(ptr, 0x14), shl(0x60, implementation)) -- mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) -- instance := create2(0, ptr, 0x37, salt) -+ mstore(ptr, 0x602d8060093d393df3363d3d373d3d3d363d7300000000000000000000000000) -+ mstore(add(ptr, 0x13), shl(0x60, implementation)) -+ mstore(add(ptr, 0x27), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) -+ instance := create2(0, ptr, 0x36, salt) - } - require(instance != address(0), "ERC1167: create2 failed"); - } -@@ -64,13 +64,13 @@ - /// @solidity memory-safe-assembly - assembly { - let ptr := mload(0x40) -- mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) -- mstore(add(ptr, 0x14), shl(0x60, implementation)) -- mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000) -- mstore(add(ptr, 0x38), shl(0x60, deployer)) -- mstore(add(ptr, 0x4c), salt) -- mstore(add(ptr, 0x6c), keccak256(ptr, 0x37)) -- predicted := keccak256(add(ptr, 0x37), 0x55) -+ mstore(ptr, 0x602d8060093d393df3363d3d373d3d3d363d7300000000000000000000000000) -+ mstore(add(ptr, 0x13), shl(0x60, implementation)) -+ mstore(add(ptr, 0x27), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000) -+ mstore(add(ptr, 0x37), shl(0x60, deployer)) -+ mstore(add(ptr, 0x4b), salt) -+ mstore(add(ptr, 0x6b), keccak256(ptr, 0x36)) -+ predicted := keccak256(add(ptr, 0x36), 0x55) - } - } - -diff -ruN proxy/ERC1967/ERC1967Proxy.sol proxy/ERC1967/ERC1967Proxy.sol ---- proxy/ERC1967/ERC1967Proxy.sol 2022-08-11 21:28:00.000000000 -0700 -+++ proxy/ERC1967/ERC1967Proxy.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -20,6 +20,7 @@ - * function call, and allows initializing the storage of the proxy like a Solidity constructor. - */ - constructor(address _logic, bytes memory _data) payable { -+ assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); - _upgradeToAndCall(_logic, _data, false); - } - diff -ruN proxy/beacon/BeaconProxy.sol proxy/beacon/BeaconProxy.sol ---- proxy/beacon/BeaconProxy.sol 2022-08-11 21:28:00.000000000 -0700 -+++ proxy/beacon/BeaconProxy.sol 2022-08-11 21:28:36.000000000 -0700 +--- proxy/beacon/BeaconProxy.sol 2022-09-09 10:15:55.890509851 +0200 ++++ proxy/beacon/BeaconProxy.sol 2022-09-20 14:34:24.806582310 +0200 @@ -28,6 +28,7 @@ * - `beacon` must be a contract with the interface {IBeacon}. */ @@ -406,9 +351,70 @@ diff -ruN proxy/beacon/BeaconProxy.sol proxy/beacon/BeaconProxy.sol _upgradeBeaconToAndCall(beacon, data, false); } +diff -ruN proxy/Clones.sol proxy/Clones.sol +--- proxy/Clones.sol 2022-09-20 14:24:58.013407601 +0200 ++++ proxy/Clones.sol 2022-09-20 14:59:00.690035663 +0200 +@@ -27,10 +27,10 @@ + assembly { + // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes + // of the `implementation` address with the bytecode before the address. +- mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) ++ mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x602d8060093d393df3363d3d373d3d3d363d73000000)) + // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. + mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) +- instance := create(0, 0x09, 0x37) ++ instance := create(0, 0x0A, 0x36) + } + require(instance != address(0), "ERC1167: create failed"); + } +@@ -47,10 +47,10 @@ + assembly { + // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes + // of the `implementation` address with the bytecode before the address. +- mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) ++ mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x602d8060093d393df3363d3d373d3d3d363d73000000)) + // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. + mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) +- instance := create2(0, 0x09, 0x37, salt) ++ instance := create2(0, 0x0A, 0x36, salt) + } + require(instance != address(0), "ERC1167: create2 failed"); + } +@@ -66,13 +66,13 @@ + /// @solidity memory-safe-assembly + assembly { + let ptr := mload(0x40) +- mstore(add(ptr, 0x38), deployer) +- mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) +- mstore(add(ptr, 0x14), implementation) +- mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) +- mstore(add(ptr, 0x58), salt) +- mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) +- predicted := keccak256(add(ptr, 0x43), 0x55) ++ mstore(add(ptr, 0x37), deployer) ++ mstore(add(ptr, 0x23), 0x5af43d82803e903d91602b57fd5bf3ff) ++ mstore(add(ptr, 0x13), implementation) ++ mstore(ptr, 0x602d8060093d393df3363d3d373d3d3d363d73) ++ mstore(add(ptr, 0x57), salt) ++ mstore(add(ptr, 0x77), keccak256(add(ptr, 0x0b), 0x36)) ++ predicted := keccak256(add(ptr, 0x44), 0x55) + } + } + +diff -ruN proxy/ERC1967/ERC1967Proxy.sol proxy/ERC1967/ERC1967Proxy.sol +--- proxy/ERC1967/ERC1967Proxy.sol 2022-09-09 10:15:55.890509851 +0200 ++++ proxy/ERC1967/ERC1967Proxy.sol 2022-09-20 14:34:24.806582310 +0200 +@@ -20,6 +20,7 @@ + * function call, and allows initializing the storage of the proxy like a Solidity constructor. + */ + constructor(address _logic, bytes memory _data) payable { ++ assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); + _upgradeToAndCall(_logic, _data, false); + } + diff -ruN proxy/transparent/TransparentUpgradeableProxy.sol proxy/transparent/TransparentUpgradeableProxy.sol ---- proxy/transparent/TransparentUpgradeableProxy.sol 2022-08-11 21:28:00.000000000 -0700 -+++ proxy/transparent/TransparentUpgradeableProxy.sol 2022-08-11 21:28:36.000000000 -0700 +--- proxy/transparent/TransparentUpgradeableProxy.sol 2022-09-09 10:15:55.890509851 +0200 ++++ proxy/transparent/TransparentUpgradeableProxy.sol 2022-09-20 14:34:24.806582310 +0200 @@ -36,6 +36,7 @@ address admin_, bytes memory _data @@ -418,8 +424,8 @@ diff -ruN proxy/transparent/TransparentUpgradeableProxy.sol proxy/transparent/Tr } diff -ruN proxy/utils/Initializable.sol proxy/utils/Initializable.sol ---- proxy/utils/Initializable.sol 2022-08-11 21:28:00.000000000 -0700 -+++ proxy/utils/Initializable.sol 2022-08-11 21:28:36.000000000 -0700 +--- proxy/utils/Initializable.sol 2022-09-20 11:16:48.456850883 +0200 ++++ proxy/utils/Initializable.sol 2022-09-20 14:34:24.806582310 +0200 @@ -59,12 +59,12 @@ * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool @@ -435,172 +441,9 @@ diff -ruN proxy/utils/Initializable.sol proxy/utils/Initializable.sol /** * @dev Triggered when the contract has been initialized or reinitialized. -diff -ruN proxy/utils/Initializable.sol.orig proxy/utils/Initializable.sol.orig ---- proxy/utils/Initializable.sol.orig 1969-12-31 16:00:00.000000000 -0800 -+++ proxy/utils/Initializable.sol.orig 2022-08-11 21:28:36.000000000 -0700 -@@ -0,0 +1,138 @@ -+// SPDX-License-Identifier: MIT -+// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) -+ -+pragma solidity ^0.8.2; -+ -+import "../../utils/Address.sol"; -+ -+/** -+ * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed -+ * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an -+ * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer -+ * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. -+ * -+ * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be -+ * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in -+ * case an upgrade adds a module that needs to be initialized. -+ * -+ * For example: -+ * -+ * [.hljs-theme-light.nopadding] -+ * ``` -+ * contract MyToken is ERC20Upgradeable { -+ * function initialize() initializer public { -+ * __ERC20_init("MyToken", "MTK"); -+ * } -+ * } -+ * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { -+ * function initializeV2() reinitializer(2) public { -+ * __ERC20Permit_init("MyToken"); -+ * } -+ * } -+ * ``` -+ * -+ * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as -+ * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. -+ * -+ * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure -+ * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. -+ * -+ * [CAUTION] -+ * ==== -+ * Avoid leaving a contract uninitialized. -+ * -+ * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation -+ * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke -+ * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: -+ * -+ * [.hljs-theme-light.nopadding] -+ * ``` -+ * /// @custom:oz-upgrades-unsafe-allow constructor -+ * constructor() { -+ * _disableInitializers(); -+ * } -+ * ``` -+ * ==== -+ */ -+abstract contract Initializable { -+ /** -+ * @dev Indicates that the contract has been initialized. -+ * @custom:oz-retyped-from bool -+ */ -+ uint8 private _initialized; -+ -+ /** -+ * @dev Indicates that the contract is in the process of being initialized. -+ */ -+ bool private _initializing; -+ -+ /** -+ * @dev Triggered when the contract has been initialized or reinitialized. -+ */ -+ event Initialized(uint8 version); -+ -+ /** -+ * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, -+ * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. -+ */ -+ modifier initializer() { -+ bool isTopLevelCall = !_initializing; -+ require( -+ (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), -+ "Initializable: contract is already initialized" -+ ); -+ _initialized = 1; -+ if (isTopLevelCall) { -+ _initializing = true; -+ } -+ _; -+ if (isTopLevelCall) { -+ _initializing = false; -+ emit Initialized(1); -+ } -+ } -+ -+ /** -+ * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the -+ * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be -+ * used to initialize parent contracts. -+ * -+ * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original -+ * initialization step. This is essential to configure modules that are added through upgrades and that require -+ * initialization. -+ * -+ * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in -+ * a contract, executing them in the right order is up to the developer or operator. -+ */ -+ modifier reinitializer(uint8 version) { -+ require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); -+ _initialized = version; -+ _initializing = true; -+ _; -+ _initializing = false; -+ emit Initialized(version); -+ } -+ -+ /** -+ * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the -+ * {initializer} and {reinitializer} modifiers, directly or indirectly. -+ */ -+ modifier onlyInitializing() { -+ require(_initializing, "Initializable: contract is not initializing"); -+ _; -+ } -+ -+ /** -+ * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. -+ * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized -+ * to any version. It is recommended to use this to lock implementation contracts that are designed to be called -+ * through proxies. -+ */ -+ function _disableInitializers() internal virtual { -+ require(!_initializing, "Initializable: contract is initializing"); -+ if (_initialized < type(uint8).max) { -+ _initialized = type(uint8).max; -+ emit Initialized(type(uint8).max); -+ } -+ } -+} -diff -ruN proxy/utils/Initializable.sol.rej proxy/utils/Initializable.sol.rej ---- proxy/utils/Initializable.sol.rej 1969-12-31 16:00:00.000000000 -0800 -+++ proxy/utils/Initializable.sol.rej 2022-08-11 21:28:36.000000000 -0700 -@@ -0,0 +1,17 @@ -+*************** -+*** 130,136 **** -+ _setInitializedVersion(type(uint8).max); -+ } -+ -+- function _setInitializedVersion(uint8 version) private returns (bool) { -+ // If the contract is initializing we ignore whether _initialized is set in order to support multiple -+ // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level -+ // of initializers, because in other contexts the contract may have been reentered. -+--- 130,136 ---- -+ _setInitializedVersion(type(uint8).max); -+ } -+ -++ function _setInitializedVersion(uint8 version) internal returns (bool) { -+ // If the contract is initializing we ignore whether _initialized is set in order to support multiple -+ // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level -+ // of initializers, because in other contexts the contract may have been reentered. diff -ruN security/Pausable.sol security/Pausable.sol ---- security/Pausable.sol 2022-08-11 21:28:00.000000000 -0700 -+++ security/Pausable.sol 2022-08-11 21:28:36.000000000 -0700 +--- security/Pausable.sol 2022-09-09 10:15:55.890509851 +0200 ++++ security/Pausable.sol 2022-09-20 14:34:24.809915708 +0200 @@ -35,6 +35,13 @@ } @@ -656,8 +499,8 @@ diff -ruN security/Pausable.sol security/Pausable.sol /** diff -ruN token/ERC1155/ERC1155.sol token/ERC1155/ERC1155.sol ---- token/ERC1155/ERC1155.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC1155/ERC1155.sol 2022-08-11 21:28:36.000000000 -0700 +--- token/ERC1155/ERC1155.sol 2022-09-20 11:01:10.432848512 +0200 ++++ token/ERC1155/ERC1155.sol 2022-09-20 14:34:24.809915708 +0200 @@ -21,7 +21,7 @@ using Address for address; @@ -686,9 +529,9 @@ diff -ruN token/ERC1155/ERC1155.sol token/ERC1155/ERC1155.sol try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response diff -ruN token/ERC20/ERC20.sol token/ERC20/ERC20.sol ---- token/ERC20/ERC20.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/ERC20.sol 2022-08-11 23:01:50.000000000 -0700 -@@ -277,7 +277,7 @@ +--- token/ERC20/ERC20.sol 2022-09-20 13:34:47.024598756 +0200 ++++ token/ERC20/ERC20.sol 2022-09-20 14:34:24.809915708 +0200 +@@ -282,7 +282,7 @@ * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ @@ -697,33 +540,12 @@ diff -ruN token/ERC20/ERC20.sol token/ERC20/ERC20.sol require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); -diff -ruN token/ERC20/README.adoc token/ERC20/README.adoc ---- token/ERC20/README.adoc 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/README.adoc 2022-08-11 21:28:36.000000000 -0700 -@@ -24,7 +24,7 @@ - * {ERC20Votes}: support for voting and vote delegation. - * {ERC20VotesComp}: support for voting and vote delegation (compatible with Compound's token, with uint96 restrictions). - * {ERC20Wrapper}: wrapper to create an ERC20 backed by another ERC20, with deposit and withdraw methods. Useful in conjunction with {ERC20Votes}. --* {ERC4626}: tokenized vault that manages shares (represented as ERC20) that are backed by assets (another ERC20). -+* {ERC20TokenizedVault}: tokenized vault that manages shares (represented as ERC20) that are backed by assets (another ERC20). - - Finally, there are some utilities to interact with ERC20 contracts in various ways. - -@@ -63,7 +63,7 @@ - - {{ERC20FlashMint}} - --{{ERC4626}} -+{{ERC20TokenizedVault}} - - == Draft EIPs - diff -ruN token/ERC20/extensions/ERC20FlashMint.sol token/ERC20/extensions/ERC20FlashMint.sol ---- token/ERC20/extensions/ERC20FlashMint.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/extensions/ERC20FlashMint.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -40,9 +40,11 @@ - require(token == address(this), "ERC20FlashMint: wrong token"); +--- token/ERC20/extensions/ERC20FlashMint.sol 2022-09-20 11:01:10.432848512 +0200 ++++ token/ERC20/extensions/ERC20FlashMint.sol 2022-09-20 14:34:24.809915708 +0200 +@@ -51,9 +51,11 @@ // silence warning about unused variable without the addition of bytecode. + token; amount; - return 0; + return fee; // HARNESS: made "return" nonzero @@ -735,8 +557,8 @@ diff -ruN token/ERC20/extensions/ERC20FlashMint.sol token/ERC20/extensions/ERC20 * @dev Returns the receiver address of the flash fee. By default this * implementation returns the address(0) which means the fee amount will be burnt. diff -ruN token/ERC20/extensions/ERC20TokenizedVault.sol token/ERC20/extensions/ERC20TokenizedVault.sol ---- token/ERC20/extensions/ERC20TokenizedVault.sol 1969-12-31 16:00:00.000000000 -0800 -+++ token/ERC20/extensions/ERC20TokenizedVault.sol 2022-08-11 21:28:36.000000000 -0700 +--- token/ERC20/extensions/ERC20TokenizedVault.sol 1970-01-01 01:00:00.000000000 +0100 ++++ token/ERC20/extensions/ERC20TokenizedVault.sol 2022-09-20 14:34:24.809915708 +0200 @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: MIT + @@ -956,8 +778,8 @@ diff -ruN token/ERC20/extensions/ERC20TokenizedVault.sol token/ERC20/extensions/ + } +} diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Votes.sol ---- token/ERC20/extensions/ERC20Votes.sol 2022-08-11 21:16:57.000000000 -0700 -+++ token/ERC20/extensions/ERC20Votes.sol 2022-08-11 22:47:30.000000000 -0700 +--- token/ERC20/extensions/ERC20Votes.sol 2022-09-20 14:24:58.016740934 +0200 ++++ token/ERC20/extensions/ERC20Votes.sol 2022-09-20 15:05:11.770836991 +0200 @@ -33,8 +33,8 @@ bytes32 private constant _DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); @@ -969,7 +791,7 @@ diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Vote Checkpoint[] private _totalSupplyCheckpoints; /** -@@ -152,7 +152,7 @@ +@@ -165,7 +165,7 @@ /** * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). */ @@ -978,7 +800,7 @@ diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Vote return type(uint224).max; } -@@ -163,16 +163,16 @@ +@@ -176,16 +176,16 @@ super._mint(account, amount); require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); @@ -998,16 +820,7 @@ diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Vote } /** -@@ -187,7 +187,7 @@ - ) internal virtual override { - super._afterTokenTransfer(from, to, amount); - -- _moveVotingPower(delegates(from), delegates(to), amount); -+ _moveVotingPower(delegates(from), delegates(to), amount); - } - - /** -@@ -195,7 +195,7 @@ +@@ -208,7 +208,7 @@ * * Emits events {DelegateChanged} and {DelegateVotesChanged}. */ @@ -1016,41 +829,42 @@ diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Vote address currentDelegate = delegates(delegator); uint256 delegatorBalance = balanceOf(delegator); _delegates[delegator] = delegatee; -@@ -212,25 +212,25 @@ +@@ -225,12 +225,13 @@ ) private { if (src != dst && amount > 0) { if (src != address(0)) { - (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); -+ (uint256 oldWeight, uint256 newWeight) = _writeCheckpointSub(_checkpoints[src], amount); // HARNESS: new version without pointer ++ (uint256 oldWeight, uint256 newWeight) = _writeCheckpointSub(_checkpoints[src], amount); // HARNESS: new version without pointer ++ emit DelegateVotesChanged(src, oldWeight, newWeight); } if (dst != address(0)) { - (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); -+ (uint256 oldWeight, uint256 newWeight) = _writeCheckpointAdd(_checkpoints[dst], amount); // HARNESS: new version without pointer ++ (uint256 oldWeight, uint256 newWeight) = _writeCheckpointAdd(_checkpoints[dst], amount); // HARNESS: new version without pointer emit DelegateVotesChanged(dst, oldWeight, newWeight); } } - } - -- function _writeCheckpoint( -+ // HARNESS: split _writeCheckpoint() to two functions as a workaround for function pointers that cannot be managed by the tool -+ function _writeCheckpointAdd( - Checkpoint[] storage ckpts, -- function(uint256, uint256) view returns (uint256) op, - uint256 delta - ) private returns (uint256 oldWeight, uint256 newWeight) { - uint256 pos = ckpts.length; - oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; -- newWeight = op(oldWeight, delta); -+ newWeight = _add(oldWeight, delta); - - if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { - ckpts[pos - 1].votes = SafeCast.toUint224(newWeight); -@@ -239,6 +239,39 @@ +@@ -255,6 +256,55 @@ } } ++ // HARNESS: split _writeCheckpoint() to two functions as a workaround for function pointers that cannot be managed by the tool ++ function _writeCheckpointAdd( ++ Checkpoint[] storage ckpts, ++ uint256 delta ++ ) private returns (uint256 oldWeight, uint256 newWeight) { ++ uint256 pos = ckpts.length; ++ oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; ++ newWeight = _add(oldWeight, delta); ++ ++ if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { ++ ckpts[pos - 1].votes = SafeCast.toUint224(newWeight); ++ } else { ++ ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)})); ++ } ++ } ++ + function _writeCheckpointSub( + Checkpoint[] storage ckpts, + uint256 delta @@ -1088,8 +902,8 @@ diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Vote return a + b; } diff -ruN token/ERC20/extensions/ERC20Wrapper.sol token/ERC20/extensions/ERC20Wrapper.sol ---- token/ERC20/extensions/ERC20Wrapper.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/extensions/ERC20Wrapper.sol 2022-08-11 21:29:19.000000000 -0700 +--- token/ERC20/extensions/ERC20Wrapper.sol 2022-08-31 13:44:36.381058287 +0200 ++++ token/ERC20/extensions/ERC20Wrapper.sol 2022-09-20 14:34:24.809915708 +0200 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/ERC20Wrapper.sol) @@ -1124,230 +938,30 @@ diff -ruN token/ERC20/extensions/ERC20Wrapper.sol token/ERC20/extensions/ERC20Wr uint256 value = underlying.balanceOf(address(this)) - totalSupply(); _mint(account, value); return value; -diff -ruN token/ERC20/extensions/ERC4626.sol token/ERC20/extensions/ERC4626.sol ---- token/ERC20/extensions/ERC4626.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/extensions/ERC4626.sol 1969-12-31 16:00:00.000000000 -0800 -@@ -1,217 +0,0 @@ --// SPDX-License-Identifier: MIT -- --pragma solidity ^0.8.0; -- --import "../ERC20.sol"; --import "../utils/SafeERC20.sol"; --import "../../../interfaces/IERC4626.sol"; --import "../../../utils/math/Math.sol"; -- --/** -- * @dev Implementation of the ERC4626 "Tokenized Vault Standard" as defined in -- * https://eips.ethereum.org/EIPS/eip-4626[EIP-4626]. -- * -- * This extension allows the minting and burning of "shares" (represented using the ERC20 inheritance) in exchange for -- * underlying "assets" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends -- * the ERC20 standard. Any additional extensions included along it would affect the "shares" token represented by this -- * contract and not the "assets" token which is an independent contract. -- * -- * _Available since v4.7._ -- */ --abstract contract ERC4626 is ERC20, IERC4626 { -- using Math for uint256; -- -- IERC20Metadata private immutable _asset; -- -- /** -- * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777). -- */ -- constructor(IERC20Metadata asset_) { -- _asset = asset_; -- } -- -- /** @dev See {IERC4262-asset} */ -- function asset() public view virtual override returns (address) { -- return address(_asset); -- } -- -- /** @dev See {IERC4262-totalAssets} */ -- function totalAssets() public view virtual override returns (uint256) { -- return _asset.balanceOf(address(this)); -- } -- -- /** @dev See {IERC4262-convertToShares} */ -- function convertToShares(uint256 assets) public view virtual override returns (uint256 shares) { -- return _convertToShares(assets, Math.Rounding.Down); -- } -- -- /** @dev See {IERC4262-convertToAssets} */ -- function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets) { -- return _convertToAssets(shares, Math.Rounding.Down); -- } -- -- /** @dev See {IERC4262-maxDeposit} */ -- function maxDeposit(address) public view virtual override returns (uint256) { -- return _isVaultCollateralized() ? type(uint256).max : 0; -- } -- -- /** @dev See {IERC4262-maxMint} */ -- function maxMint(address) public view virtual override returns (uint256) { -- return type(uint256).max; -- } -- -- /** @dev See {IERC4262-maxWithdraw} */ -- function maxWithdraw(address owner) public view virtual override returns (uint256) { -- return _convertToAssets(balanceOf(owner), Math.Rounding.Down); -- } -- -- /** @dev See {IERC4262-maxRedeem} */ -- function maxRedeem(address owner) public view virtual override returns (uint256) { -- return balanceOf(owner); -- } -- -- /** @dev See {IERC4262-previewDeposit} */ -- function previewDeposit(uint256 assets) public view virtual override returns (uint256) { -- return _convertToShares(assets, Math.Rounding.Down); -- } -- -- /** @dev See {IERC4262-previewMint} */ -- function previewMint(uint256 shares) public view virtual override returns (uint256) { -- return _convertToAssets(shares, Math.Rounding.Up); -- } -- -- /** @dev See {IERC4262-previewWithdraw} */ -- function previewWithdraw(uint256 assets) public view virtual override returns (uint256) { -- return _convertToShares(assets, Math.Rounding.Up); -- } -- -- /** @dev See {IERC4262-previewRedeem} */ -- function previewRedeem(uint256 shares) public view virtual override returns (uint256) { -- return _convertToAssets(shares, Math.Rounding.Down); -- } -- -- /** @dev See {IERC4262-deposit} */ -- function deposit(uint256 assets, address receiver) public virtual override returns (uint256) { -- require(assets <= maxDeposit(receiver), "ERC4626: deposit more than max"); -- -- uint256 shares = previewDeposit(assets); -- _deposit(_msgSender(), receiver, assets, shares); -- -- return shares; -- } -- -- /** @dev See {IERC4262-mint} */ -- function mint(uint256 shares, address receiver) public virtual override returns (uint256) { -- require(shares <= maxMint(receiver), "ERC4626: mint more than max"); -- -- uint256 assets = previewMint(shares); -- _deposit(_msgSender(), receiver, assets, shares); -- -- return assets; -- } -- -- /** @dev See {IERC4262-withdraw} */ -- function withdraw( -- uint256 assets, -- address receiver, -- address owner -- ) public virtual override returns (uint256) { -- require(assets <= maxWithdraw(owner), "ERC4626: withdraw more than max"); -- -- uint256 shares = previewWithdraw(assets); -- _withdraw(_msgSender(), receiver, owner, assets, shares); -- -- return shares; -- } -- -- /** @dev See {IERC4262-redeem} */ -- function redeem( -- uint256 shares, -- address receiver, -- address owner -- ) public virtual override returns (uint256) { -- require(shares <= maxRedeem(owner), "ERC4626: redeem more than max"); -- -- uint256 assets = previewRedeem(shares); -- _withdraw(_msgSender(), receiver, owner, assets, shares); -- -- return assets; -- } -- -- /** -- * @dev Internal convertion function (from assets to shares) with support for rounding direction -- * -- * Will revert if assets > 0, totalSupply > 0 and totalAssets = 0. That corresponds to a case where any asset -- * would represent an infinite amout of shares. -- */ -- function _convertToShares(uint256 assets, Math.Rounding rounding) internal view virtual returns (uint256 shares) { -- uint256 supply = totalSupply(); -- return -- (assets == 0 || supply == 0) -- ? assets.mulDiv(10**decimals(), 10**_asset.decimals(), rounding) -- : assets.mulDiv(supply, totalAssets(), rounding); -- } -- -- /** -- * @dev Internal convertion function (from shares to assets) with support for rounding direction -- */ -- function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256 assets) { -- uint256 supply = totalSupply(); -- return -- (supply == 0) -- ? shares.mulDiv(10**_asset.decimals(), 10**decimals(), rounding) -- : shares.mulDiv(totalAssets(), supply, rounding); -- } -- -- /** -- * @dev Deposit/mint common workflow -- */ -- function _deposit( -- address caller, -- address receiver, -- uint256 assets, -- uint256 shares -- ) private { -- // If _asset is ERC777, `transferFrom` can trigger a reenterancy BEFORE the transfer happens through the -- // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer, -- // calls the vault, which is assumed not malicious. -- // -- // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the -- // assets are transfered and before the shares are minted, which is a valid state. -- // slither-disable-next-line reentrancy-no-eth -- SafeERC20.safeTransferFrom(_asset, caller, address(this), assets); -- _mint(receiver, shares); -- -- emit Deposit(caller, receiver, assets, shares); -- } -- -- /** -- * @dev Withdraw/redeem common workflow -- */ -- function _withdraw( -- address caller, -- address receiver, -- address owner, -- uint256 assets, -- uint256 shares -- ) private { -- if (caller != owner) { -- _spendAllowance(owner, caller, shares); -- } -- -- // If _asset is ERC777, `transfer` can trigger trigger a reentrancy AFTER the transfer happens through the -- // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer, -- // calls the vault, which is assumed not malicious. -- // -- // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the -- // shares are burned and after the assets are transfered, which is a valid state. -- _burn(owner, shares); -- SafeERC20.safeTransfer(_asset, receiver, assets); -- -- emit Withdraw(caller, receiver, owner, assets, shares); -- } -- -- function _isVaultCollateralized() private view returns (bool) { -- return totalAssets() > 0 || totalSupply() == 0; -- } --} +diff -ruN token/ERC20/README.adoc token/ERC20/README.adoc +--- token/ERC20/README.adoc 2022-09-20 13:34:47.024598756 +0200 ++++ token/ERC20/README.adoc 2022-09-20 14:34:24.809915708 +0200 +@@ -24,7 +24,7 @@ + * {ERC20Votes}: support for voting and vote delegation. + * {ERC20VotesComp}: support for voting and vote delegation (compatible with Compound's token, with uint96 restrictions). + * {ERC20Wrapper}: wrapper to create an ERC20 backed by another ERC20, with deposit and withdraw methods. Useful in conjunction with {ERC20Votes}. +-* {ERC4626}: tokenized vault that manages shares (represented as ERC20) that are backed by assets (another ERC20). ++* {ERC20TokenizedVault}: tokenized vault that manages shares (represented as ERC20) that are backed by assets (another ERC20). + + Finally, there are some utilities to interact with ERC20 contracts in various ways. + +@@ -63,7 +63,7 @@ + + {{ERC20FlashMint}} + +-{{ERC4626}} ++{{ERC20TokenizedVault}} + + == Draft EIPs + diff -ruN token/ERC20/utils/SafeERC20.sol token/ERC20/utils/SafeERC20.sol ---- token/ERC20/utils/SafeERC20.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC20/utils/SafeERC20.sol 2022-08-11 21:28:36.000000000 -0700 +--- token/ERC20/utils/SafeERC20.sol 2022-09-09 10:15:55.893843970 +0200 ++++ token/ERC20/utils/SafeERC20.sol 2022-09-20 14:34:28.259983206 +0200 @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; @@ -1380,9 +994,9 @@ diff -ruN token/ERC20/utils/SafeERC20.sol token/ERC20/utils/SafeERC20.sol * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). diff -ruN token/ERC721/extensions/draft-ERC721Votes.sol token/ERC721/extensions/draft-ERC721Votes.sol ---- token/ERC721/extensions/draft-ERC721Votes.sol 2022-08-11 21:28:00.000000000 -0700 -+++ token/ERC721/extensions/draft-ERC721Votes.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -34,7 +34,7 @@ +--- token/ERC721/extensions/draft-ERC721Votes.sol 2022-09-20 14:24:58.016740934 +0200 ++++ token/ERC721/extensions/draft-ERC721Votes.sol 2022-09-20 14:34:28.259983206 +0200 +@@ -49,7 +49,7 @@ /** * @dev Returns the balance of `account`. */ @@ -1392,95 +1006,95 @@ diff -ruN token/ERC721/extensions/draft-ERC721Votes.sol token/ERC721/extensions/ } } diff -ruN utils/Address.sol utils/Address.sol ---- utils/Address.sol 2022-08-11 21:28:00.000000000 -0700 -+++ utils/Address.sol 2022-08-11 21:28:36.000000000 -0700 +--- utils/Address.sol 2022-09-20 11:01:10.432848512 +0200 ++++ utils/Address.sol 2022-09-20 14:34:28.259983206 +0200 @@ -131,6 +131,7 @@ uint256 value, string memory errorMessage ) internal returns (bytes memory) { + return ""; // external calls havoc require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); diff -ruN utils/math/Math.sol utils/math/Math.sol ---- utils/math/Math.sol 2022-08-11 21:28:00.000000000 -0700 -+++ utils/math/Math.sol 2022-08-11 21:28:36.000000000 -0700 -@@ -149,78 +149,4 @@ +--- utils/math/Math.sol 2022-09-20 14:24:58.016740934 +0200 ++++ utils/math/Math.sol 2022-09-20 14:34:29.036665098 +0200 +@@ -342,4 +342,78 @@ + return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } - return result; } -- -- /** -- * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. -- * -- * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). -- */ -- function sqrt(uint256 a) internal pure returns (uint256) { -- if (a == 0) { -- return 0; -- } -- -- // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. -- // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have -- // `msb(a) <= a < 2*msb(a)`. -- // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. -- // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. -- // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a -- // good first aproximation of `sqrt(a)` with at least 1 correct bit. -- uint256 result = 1; -- uint256 x = a; -- if (x >> 128 > 0) { -- x >>= 128; -- result <<= 64; -- } -- if (x >> 64 > 0) { -- x >>= 64; -- result <<= 32; -- } -- if (x >> 32 > 0) { -- x >>= 32; -- result <<= 16; -- } -- if (x >> 16 > 0) { -- x >>= 16; -- result <<= 8; -- } -- if (x >> 8 > 0) { -- x >>= 8; -- result <<= 4; -- } -- if (x >> 4 > 0) { -- x >>= 4; -- result <<= 2; -- } -- if (x >> 2 > 0) { -- result <<= 1; -- } -- -- // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, -- // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at -- // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision -- // into the expected uint128 result. -- unchecked { -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- result = (result + a / result) >> 1; -- return min(result, a / result); -- } -- } -- -- /** -- * @notice Calculates sqrt(a), following the selected rounding direction. -- */ -- function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { -- uint256 result = sqrt(a); -- if (rounding == Rounding.Up && result * result < a) { -- result += 1; -- } -- return result; -- } ++ ++ /** ++ * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. ++ * ++ * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). ++ */ ++ function sqrt(uint256 a) internal pure returns (uint256) { ++ if (a == 0) { ++ return 0; ++ } ++ ++ // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. ++ // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have ++ // `msb(a) <= a < 2*msb(a)`. ++ // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. ++ // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. ++ // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a ++ // good first aproximation of `sqrt(a)` with at least 1 correct bit. ++ uint256 result = 1; ++ uint256 x = a; ++ if (x >> 128 > 0) { ++ x >>= 128; ++ result <<= 64; ++ } ++ if (x >> 64 > 0) { ++ x >>= 64; ++ result <<= 32; ++ } ++ if (x >> 32 > 0) { ++ x >>= 32; ++ result <<= 16; ++ } ++ if (x >> 16 > 0) { ++ x >>= 16; ++ result <<= 8; ++ } ++ if (x >> 8 > 0) { ++ x >>= 8; ++ result <<= 4; ++ } ++ if (x >> 4 > 0) { ++ x >>= 4; ++ result <<= 2; ++ } ++ if (x >> 2 > 0) { ++ result <<= 1; ++ } ++ ++ // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, ++ // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at ++ // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision ++ // into the expected uint128 result. ++ unchecked { ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ result = (result + a / result) >> 1; ++ return min(result, a / result); ++ } ++ } ++ ++ /** ++ * @notice Calculates sqrt(a), following the selected rounding direction. ++ */ ++ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { ++ uint256 result = sqrt(a); ++ if (rounding == Rounding.Up && result * result < a) { ++ result += 1; ++ } ++ return result; ++ } }