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

Vault #220

Open
wants to merge 82 commits into
base: master
Choose a base branch
from
Open

Vault #220

wants to merge 82 commits into from

Conversation

markspanbroek
Copy link
Member

@markspanbroek markspanbroek commented Feb 6, 2025

Adds a Vault contract, that allows funds to be locked up for a certain amount of time. These funds can be transferred, burned or even flow over time to other addresses.

Follows the design from codex-research/design/contract-deployment

Requires #219 to be merged first.

@markspanbroek
Copy link
Member Author

Added functionality to have multiple accounts for an account holder inside a fund. This ensures that in the codex marketplace we keep funds for the client and for each slot separate, even though some providers may choose to fill multiple slots, or a client might decide to fill a slot in the storage contract itself.

@markspanbroek markspanbroek force-pushed the vault branch 2 times, most recently from 3049325 to 724670b Compare February 24, 2025 15:13
@markspanbroek
Copy link
Member Author

Replaced 🔥 burnFund() with ❄️ freezeFund().
Freezing a fund stops all flows and disallows any further changes to the fund until it unlocks.

Copy link
Collaborator

@emizzle emizzle left a comment

Choose a reason for hiding this comment

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

Really great job Mark! Huge effort 💪 🙌

This was quite a lot to go through. I used the implementation branch (master...vault-integration#diff-5973808e32384782b5978a63e85b893b67d634be8aa42001f0ef480f189a0688R179) to get a better understanding of how some of the functionality relates to the Marketplace.

One question:
When we discussed freezing the vault, we discussed that it would not be able to be unfrozen by a controlling party. In this implementation, unfreezing happens after some time has elapsed, making the funds withdrawable again. Is the idea here that in the case of an attack, the vaults would all be locked in some way with a very long expiry?

LockStatus lockStatus = lock.status();
if (lockStatus == LockStatus.Locked) {
Account memory account = _accounts[controller][fund][id];
account.update(Timestamps.currentTime());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I find update a bit awkward in the context of a view, where nothing is being stored, except for in memory. Maybe atEnd or simulateEndAt...?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was also bit puzzled by this 😅 Maybe a better name would better convey what is happening here and why. I like the "simulate" word from Eric's suggestion, but then it does not make sense in the cases where the account is actually stored?

Copy link
Member Author

@markspanbroek markspanbroek Mar 3, 2025

Choose a reason for hiding this comment

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

I also find it bit hard to find a better name, because it updates the struct that you pass as a parameter. Names such as atEnd() or simulateAtEnd() suggest to me that there would be a return value with the calculated values.

Maybe updateFlow()?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe updateSelf? Or updateSelfAtEnd?

Copy link
Member

@AuHau AuHau left a comment

Choose a reason for hiding this comment

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

Great work Mark! 🎉

I don't see any big problem with the general approach and design here. My only concern is the usage of the uint128 for the balance tracking. See my comment bellow.

This is big PR, so this is just my first iteration of review. Will do more later on.

Comment on lines +21 to +26
struct Balance {
/// Available tokens can be transfered
uint128 available;
/// Designated tokens can no longer be transfered
uint128 designated;
}
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure about the uint128. I understand your reasoning, but then if this should be a "general purpose contract", doing this optimization is IMHO wrong. You also don't have balances in ERC20 tracked with uint128 even though "it should be good enough for most cases".

Copy link
Member

Choose a reason for hiding this comment

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

Looking at how this propagates to the Marketplace contract, I am more unsure about this.

Copy link
Member Author

Choose a reason for hiding this comment

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

@AuHau and I discussed this in our meeting last week. To summarize:

  • we don't expect there to be any tokens for which uint128 is insufficient
  • using uint128 saves gas costs, because less storage is used
  • uint128 could be a hindrance for the community to use the vault
    • they might have to cast from uint256 to uint128, which needs to be done with care
  • it is unclear whether the gas cost savings from having to store less bytes are worth it

I suggested to keep it at uint128 for now, and change it to uint256 if needed

LockStatus lockStatus = lock.status();
if (lockStatus == LockStatus.Locked) {
Account memory account = _accounts[controller][fund][id];
account.update(Timestamps.currentTime());
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was also bit puzzled by this 😅 Maybe a better name would better convey what is happening here and why. I like the "simulate" word from Eric's suggestion, but then it does not make sense in the cases where the account is actually stored?

@markspanbroek
Copy link
Member Author

Thanks for the good feedback @AuHau and @emizzle. I think I addressed most of the naming concerns.

One question:
When we discussed freezing the vault, we discussed that it would not be able to be unfrozen by a controlling party. In this implementation, unfreezing happens after some time has elapsed, making the funds withdrawable again. Is the idea here that in the case of an attack, the vaults would all be locked in some way with a very long expiry?

The freezeFund() function only freezes a single fund, meaning that there can be no transfers or flows anymore until the fund unlocks and withdrawal can happen. This can happen in the marketplace when a storage request fails. The freezing functionality that we discussed and wrote down in the design document is different. This is about freezing the entire contract, allowing only withdrawals, in an emergency situation where our contracts are under attack. This is implemented by the vault through the use of the Pausable contract.

Base automatically changed from update-solidity to master March 4, 2025 08:33
markspanbroek added a commit to codex-storage/codex-research that referenced this pull request Mar 10, 2025
Updates to the API of the Vault contract as worked on in codex-storage/codex-contracts-eth#220

Most important changes:
- token transfers are much more restricted in the vault, improving its safety
- when a storage request fails, only the providers at fault are punished, the rest are not
-  when a storage request fails, the client is only reimbursed for the remaining time in the contract
-  no longer possible for the marketplace to request one final storage proof before allowing withdrawal
-  repair reward is temporarily stored with the client's funds while slot is free, and not yet filled; this could lead to client withdrawing repair rewards when slots are free when the request ends
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.

3 participants