Skip to content
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

Post contest updates #57

Merged
merged 8 commits into from
Aug 22, 2024
Merged

Post contest updates #57

merged 8 commits into from
Aug 22, 2024

Conversation

sunbreak1211
Copy link
Collaborator

No description provided.

@sunbreak1211 sunbreak1211 changed the title Use owner/index as key for user functions Post contest updates Aug 14, 2024
@sunbreak1211 sunbreak1211 requested review from oldchili and telome and removed request for oldchili August 14, 2024 17:29
@sunbreak1211 sunbreak1211 marked this pull request as ready for review August 14, 2024 17:29
Copy link
Contributor

@telome telome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good.

function isUrnAuth(address urn, address usr) external view returns (bool ok) {
ok = _urnAuth(urn, usr);
function isUrnAuth(address owner, uint256 index, address usr) external view returns (bool ok) {
ok = _urnAuth(owner, _getUrn(owner, index), usr);
}

// --- urn management functions ---

function open(uint256 index) external returns (address urn) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Technically you don't need the index input, and can return it to the user along with the urn.
    The docs says it is there to prevent race condition, but by the same logic every user operation should be with a nonce to prevent him from, e.g., calling lock twice.
    Also, the consequences of a race condition in open are not so bad, as the user still owns both urns.

  2. I wonder if it make sense to let anyone open a urn on behalf of a user. and in this case, the function won't revert if the index already exist, and instead will just return the urn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget that we support multicall.

So for (1) - The user might not remember how many urns he has and passing the index can avoid mistakes such as opening urn number 3 but depositing to urn number 2.

For (2) - Also here I see cases for confusion since someone might increment the count for the user without him being aware, which may end up locking in the wrong urn. And if the index is still used for validation it can become a DOS vector on opens. In general I think this is also the type of change we'd prefer not to do at this point after the Sherlock audit.

* `wipe(address urn, uint256 wad)` - Repay `wad` amount of NST backed by the `urn`’s MKR.
* `wipeAll(address urn)` - Repay the amount of NST that is needed to wipe the `urn`s entire debt.
* `getReward(address urn, address farm, address to)` - Claim the reward generated from a farm on behalf of the `urn` and send it to the specified `to` address.
* `hope(address owner, uint256 index, address usr)` - Allow `usr` to also manage the `owner-index` `urn`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is only a matter of semantic, but maybe a name like deployer is better than owner.
It is true that currently the deployer has owner privileges in the _urnAuth function, but imo, it is more of a bug than a feature (though legit design decision).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deployer has usually other meaning in Maker scripts (the deployer of the main contract).

mapping(address owner => uint256 count) public ownerUrnsCount;
mapping(address owner => mapping(uint256 index => address urn)) public ownerUrns;
mapping(address urn => address owner) public urnOwners;
mapping(address urn => mapping(address usr => uint256 allowed)) public urnCan;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not super important, but i wonder if a mapping from owner and index to allowed (and similarly to voteDelegate, farm, auctionsCount etc) would not be more consistent.
Possibly even easier for UI integration, though i guess the UI has to be aware of the urn to query for the user debt/collateral position.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have originally made the can mapping in this PR like that way, but then I preferred to make all the mappings under urn to keep some consistency. I agree we could have moved everything to owner/index as well, but that probably ended up being a bigger change and in general the urn as index still makes sense.

function isUrnAuth(address urn, address usr) external view returns (bool ok) {
ok = _urnAuth(urn, usr);
function isUrnAuth(address owner, uint256 index, address usr) external view returns (bool ok) {
ok = _urnAuth(owner, _getUrn(owner, index), usr);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. is there a reason to revert if (owner,index) does not have a urn and in this case _getUrn will revert? it could be annoying for a UI if a view function revert.
  2. if _getUrn is not used, i wonder if you can't just make this function public and get rid of _urnAuth, but i guess it is nicer to have it the way it is now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking the urn existence is important for the lock functions in order to avoid to deposit something in a position that doesn't exist. In the prev version, validating the urn existence would require an extra storage load, so it was just implemented in those lock functions. Now that we are already consuming the extra sload, IMO just made sense to put it in the checks path everywhere.
I doubted about the consequence of reverting in isUrnAuth as well. If we consider this might be a pain in the ass for the UIs we can do it differently there.


function _getUrn(address owner, uint256 index) internal view returns (address urn) {
urn = ownerUrns[owner][index];
require(urn != address(0), "LockstakeEngine/invalid-urn");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, if you remove the check for urn != address(0) will something break?
It is probably good to have it anw, I just want to make sure i don't miss anything in the threat model.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the prev comment, not really breaking, but it is a nice check when locking. And in general it kinda feels good to first check something is valid before checking its permissions, but yeah far from being mandatory or similar.

Copy link
Contributor

@oldchili oldchili left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@DaiFoundation-DevOps
Copy link

DaiFoundation-DevOps commented Aug 22, 2024

CLA assistant check
All committers have signed the CLA.

@sunbreak1211 sunbreak1211 merged commit 8b16eac into dev Aug 22, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants