-
Notifications
You must be signed in to change notification settings - Fork 14
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: contract deployment and upgrades writeup #195
base: master
Are you sure you want to change the base?
Conversation
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.
Thanks for doing this, Adam. Very good to have all of this discussion and knowledge captured.
Regarding contract modularisation, I have a few questions/comments:
- From our initial discussion, I thought there would be a third contract that deals primarily with holding the
StorageRequest
mappings, so that the business logic and funds contracts could be upgraded without wiping the network? What was the reasoning behind leaving this out? - The
TimeVault
contract will extendERC20
and manage the spending of tokens, correct? If so, it may be worth mentioning. - We initially discussed that we'd try to limit the amount of funds that could be sent to any one address by utilising an ACL of permissible recipient addresses for a deposit. Most funds could be locked to a single address, and repair rewards could be sent to any address (
*
), which is better than allowing all funds to be sent to any address. However, the proposed API usesfromAddress
only. Would you mind explaining the reasoning? My suspicion is that this leverages the ERC20transferFrom
andapprove
functions, but IMO, that is not enough to prevent a hack from draining funds, especially given that we have already discussed adding infinite approval, meaning that the caller intransferFrom
can transfer an infinite amount of funds. I do prefer the simplicity of the outlined approach over the ACL, however, it seems there's not as much protection. - We also discussed utilising OpenZeppelin's proxy contracts for the modular contracts approach. This would enable upgrading each of the three(?) contracts, while retaining only one Marketplace address in the Codex client. However, at the start of the writeup, it is mentioned that proxy contracts provides too much power to the admin role. The admin role would have permission to update the proxy contract, but not force a user to use a specific version, as we discussed passing a contract version parameter, see next point.
- There was also discussion of passing in a version parameter from the client to the proxy contract, which in my opinion is a good way to retain the users' control over which contract to call, in the same way that having a single Marketplace contract in the client does. When one of the three(?) contracts are upgraded, a new "contracts version" is created, and the Codex client can be updated with this contracts version. The version would be passed from the Codex client to the proxy contract for each call, thus enabling users to use whichever version of the contract they desire. Users on old versions would still use the old version without issue. As you mentioned in the writeup, the limited contract duration would prevent outdated contract versions from existing for too long. This is a downside for extending the max contract duration too long.
As a general comment, perhaps you could look at checking your writing with a grammar and spell check plugin?
most probably lead to deploying a new token contract as part of a token upgrade, together with redeploying the whole | ||
marketplace contract's suite. |
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 thought that having modular funds contract separated out would allow re-deployment of only the funds contract on its own?
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.
If you have compromised the vault in a way that somebody can drain its funds and you freeze it because of it, then you deploy new fixed version - what do you do about the funds freezed in the original vault? You can not unfreeze it to "move it to the new one" because the attacker could exploit the bug because of which it was freezed for.
Dmitriy's suggestion in our session was to do a "community consensus" hard-fork of the token. Where new token would be deployed, holders of the existing tokens could redeem the new tokens for the old ones and the funds in the old vault would be replaced in the new fixed vault by mint of the new tokens.
This was proposed mainly by you at the beginning of the exploratory work on this, but I don't think it was mentioned during our design session in Lisbon. We do not need this part because we will have "upgrade" capabilities on the
While they share some similarities - no,
Already in our designing session we have scratched the "recipient based locking" as I have described in the document:
The
That is from the original document when we discussed the previous solutions. This point still stands because, as a solution, this is not passable. Only with modularisation of the contracts and splitting up the funds-keeping part into a vault in a separate contract can we actually use it for the Marketplace contract. I will review this section and its wording together with adding a note to the new section about why we can use the
I don't recall this, but generally, the "upgradability" of contracts is still reserved only for emergency/critical bug-fixing cases. In other cases the "feature upgrade" still should be used. In this way, the "versioning" is performed by the node itself, as it will monitor multiple contract versions running in parallel and submit new requests only to the newest one. In this way, we will be upgrading only the Marketplace contract, and the Vault should be persistent unless there is a critical bug fund in it in which the "emergency freezing" of it will be invoked.
Thanks for the suggestion 😅 I was using some freemium spell-checker, but now I got myself a Grammarly subscription so hopefully the level of my grammar should improve 😅 |
@emizzle after today's discussion WDYT? Can you give it another review? |
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'm still a bit confused after reading this proposal 😅
Maybe there could be some more details in there to provide some clarity around the latest proposal that combines ideas of previous proposals, particularly:
- The TimeVault and Token contracts are passed in as constructor arguments to the Marketplace contract. The codex client contains only the address of the marketplace contract (hardcoded? cli param?), which, after upgrading one of the three contracts (token, marketplace, timevault), would require an update and release of the client.
- A small paragraph about what would happen in the case of an emergency. In particular, which contracts would be affected and how would the admin interact with them. Also, it seems we are missing the idea of re-deploying the Token contract and then redeeming old tokens for new tokens at a pre-hack snapshot.
- A small paragraph about what would happen in the case of a normal upgrade, which contracts would be affected, and how the client would be affected.
- A small paragraph about the situations that would wipe the network
Business logic contract would contain the Marketplace logic, and it would be possible to perform emergency upgrades using concepts | ||
described in [Upgradable contract](#upgradable-contract) section. In this way if there is bug/exploit that would, | ||
for example, affect the funds, it would be possible to quickly patch it. The original "feature upgrade" path still holds | ||
with this approach, where this business logic contract would get upgraded as discussed in [Upgrades](#upgrades) section. | ||
The admin role would belong to multisig maintained inside the organization. This contract would not hold any funds as | ||
they would be delegated to vault contract. | ||
|
||
Vault contract has the responsibility to safe-keep user's fund. It should have minimal logic incorporated to minimize | ||
attack surface. This contract would not incorporate the upgradibility capabilities, but as a safety measure, it would be | ||
possible to freez it as described in [Freezing contract](#freezing-contract) section. Freezing the Vault would be done | ||
in case of severe exploitable bug. It would be possible to trigger it with multisig maintained inside the organization, | ||
which could be later on extended to members of the community. Once freezed the contract would not be able to unfreez later | ||
on, hence freezing the vault contract is a very impactful action which should not be taken lightly. This action would | ||
most probably lead to deploying a new token contract as part of a token upgrade, together with redeploying the whole | ||
marketplace contract's suite. |
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.
Here's a point of confusion for me. The Upgradable Contract
section describes using proxy contracts to upgrade. After the discussion we just had, I was under the impression we wouldn't be using proxy contracts (I understand i was proposing to use it for both contracts, not just one), but after re-reading this, I think you are trying to say that the TimeVault
contract would be controlled by a proxy contract to allow for quick emergency upgrades. However, in the next paragraph, you say "This contract would not incorporate the upgradibility capabilities". What are the "upgradability capabilities" referring to?
I think there are two things that should be clarified here:
- The terminology is very confusing: "Upgradable contract" vs "Upgrades". Imo, these need to be renamed to avoid confusion, maybe be something like "Upgrades via proxy contract" and "Contract replacement upgrades"
- Is the
TimeVault
contract using a proxy contract or not?
I think maybe these two paragraphs should be carefully rewritten if possible to provide maximum clarity. It's ok to reiterate the solutions proposed in previous sections, as this is more clear for the reader than having them make assumptions based on previous sections.
Writeup about codex-storage/codex-pm#51