-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: v3.0.3 #98
feat: v3.0.3 #98
Conversation
* feat: max uint deposit * fix: invariant test * fix: rebase * fix: dont max mint * fix: uint 256 Co-authored-by: FP <[email protected]> * fix: uint 256 Co-authored-by: FP <[email protected]> * test: check balances --------- Co-authored-by: FP <[email protected]>
* chore: update domain seperator * feat: dont cache domain
|
||
// Deposit full balance if using max uint. | ||
if (assets == type(uint256).max) { | ||
assets = S.asset.balanceOf(msg.sender); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case for using uint256.max
? I like this flow when repaying the debt but for deposit, I haven't seen it yet.
Will it break the ERC4626 standard: “MUST revert if all of assets
cannot be deposited”? https://eips.ethereum.org/EIPS/eip-4626#deposit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most common case we have run into is when doing multiple txns in a row, especially in a SAFE script, when the value of the underlying the wallet will have is not know.
Ex:
- Redeem 100% of shares from DAI-1
- Deposit full DAI balance into DAI-2
Since the txn executes at a different block than created the amount cannot be known exactly since DAI-1 PPS is always changing and so dust will get left behind.
It does not match 4626 exactly and would be a special case user would need to know about similar to our masLoss
additional parameter.
src/TokenizedStrategy.sol
Outdated
), | ||
keccak256(bytes(S.name)), | ||
keccak256(bytes("Yearn Vault")), | ||
keccak256(bytes(API_VERSION)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed but nice to do
You can store these values as constants for cheaper txs.
Permit2 reference: https://github.com/Uniswap/permit2/blob/cc56ad0f3439c502c246fc5cfcc3db92bb8b7219/src/EIP712.sol#L26
Simpler version:
bytes32 internal constant _TYPE_HASH = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 internal constant _NAME_HASH = keccak256("Yearn Vault");
bytes32 internal constant _VERSION_HASH = keccak256(bytes(API_VERSION));
function DOMAIN_SEPARATOR() public view returns (bytes32) {
return
keccak256(
abi.encode(
_TYPE_HASH,
_NAME_HASH,
_VERSION_HASH,
block.chainid,
address(this)
)
);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had assumed that the compiler is smart enough to store the individual hashes as constants in the bytecode even without declaring them as constants so the more readable version is preferred. Though I havent verified it is and will double check to make sure
We are removing the cached domain_seperator since it cannot be stored as immutables and have to be kept in storage which is more expensive to pull from rather than recalculating it every call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe newer versions of the compiler are smarter but this one still leaves room for gas savings:
testFuzz_permit(uint256) (gas: -114 (-0.133%))
test_permit_withExpiry() (gas: -171 (-0.183%))
test_permit_badV() (gas: -14535 (-0.185%))
test_permit_replay() (gas: -171 (-0.193%))
test_permit_badS() (gas: -114 (-0.203%))
test_permit_ownerSignerMismatch() (gas: -114 (-0.203%))
test_permit_earlyNonce() (gas: -114 (-0.204%))
test_permit_differentSpender() (gas: -114 (-0.204%))
test_permit_zeroAddress() (gas: -114 (-0.204%))
testFuzz_permit_multiple(bytes32) (gas: -1140 (-0.432%))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it appears that all of those savings are actually on coming from the _name_hash.
The other two do seem to be storing the hashes as constants but the name hash is not because it is casting the string to bytes() first before hashing it which i guess is not stored in its final form
So if we dont cast the string to bytes() which we no longer need to do cause its not pulling from storage, then it appears that the cost for permit is the same as declaring them constants outside the function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job figuring out this!
Co-authored-by: spalen0 <[email protected]>
Co-authored-by: spalen0 <[email protected]>
* fix: conversion * test: full loss * feat: add self check to max views * test: balance check * fix: spelling
Description
maxLoss
variable to the maxRedeem and maxWithdraw functions to match the multi strategy vault abi 5b15c52Fixes # (issue)
Checklist