Comments (17)
@bowenwang1996
What if the shared contract deployer want to upgrade the existing contract?
Do they need to pay again?
(ex: 300kb -> 310kb)
scenario 1: Pay 30 NEAR + Pay 31 Near = Total 61 NEAR
scenario 2: Pay 30 NEAR + Pay 1 Near = Total 31 NEAR
from neps.
@ilblackdragon the main problem here with upgrades based on some sort of label other than contract hash is that it requires a nontrivial change to the state format and the runtime implementation. Basically, instead of storing contract hash in account state, we now need to store an account id and resolve it to a specific contract at runtime. This requires introducing another account version, which is doable but requires extra efforts. I think it is probably beneficial to implement the proposal without contract upgradability in the first version. If there is a strong demand from contract developers for the upgradability feature, it can be implemented on top of the first version.
from neps.
@nujabes403 this design does not allow one to upgrade permanently deployed contract, so you need to deploy a new contract. To implement upgradability is not trivial because of two reasons: 1) currently the contract is identified by its hash and that is how a regular account can deploy a permanent contract on their account. If there is a need for upgradability this needs to be changed. 2) There needs to be a permission management system that specifies who can upgrade the contract. Because the contract is not deployed on any specific account, it becomes very messy.
What do you think is a contract that needs to be deployed on many user accounts and also need to be upgraded frequently?
from neps.
DeployPermanentContractAction
A commonly used method in EVM-based chains is:
The Proxy Contract calls the Logic Contract using delegateCall, where state storage is done through the Logic Contract in the Proxy Contract, and the Logic Contract can be replaced at any time.
This method is widely adopted by EVM-based developers. If NEAR also supports this, developers could develop more easily.
For example, if we declare a NEP 141 contract with custom logic as a Permanent Contract, and allow all deployed NEP 141 tokens to point to �the contract, when we want to change the Logic of all deployed contracts, we only need to modify the Logic Contract declared as a Permanent Contract. This would provide great convenience for developers.
In this regard, if upgradeability of permanent contracts is supported, it would be very powerful.
from neps.
I think we should make the global contract semantics as similar as possible to existing contracts. For instance, AFAIK this proposal would be the first place we have a concept of a separate 'deployer' account used to refer to a contract, but I don't think that's necessary.
So here's my mental model for how this feature could work:
- Today, each account either has contract code or doesn't have contract code.
- After this feature, there's four possibilities for each account, listed here along with the action to make each one happen:
- No contract code
- Local contract (
DeployContractAction(code)
) - Global contract (
DeployPermanentContractAction(code)
) - Global contract copy (
DeployExistingContractAction(global_contract_account_id | code_hash)
)
To upgrade a global contract (which takes effect for all account-referenced copies ASAP), you can call DeployPermanentContractAction
again using an FAK or from within the existing global contract code. If you're self-upgrading from the global contract code, that means any copies would come with a vestigial and possibly dangerous self-upgrade mechanism. So that upgrade function should be written so it only works on the main global contract.
Similarly, even if the global contract is meant to be just a template/factory that gets copied to other accounts, it might still have a working #[init]
method, so that method might be written so it only works on copies.
Other transition rules:
- You can't convert from Global to Local, i.e. if an account has called
DeployExistingContractAction
, it cannot callDeployContractAction
. - Can you go from Global to Global Copy, or from Global Copy to Global or Local? Maybe. I can think of some use cases for those capabilities, but they're not vital so it wouldn't be worth complicating the implementation.
from neps.
I'm trying to understand the motivation. Is it this one:
Using global contracts deployed by third parties is unsafe because they can upgrade them at any time. Instead, you should first copy the contract and then reference the copy for your contracts. Is this correct?
Kind of. But yes, the issue here is who is allowed to upgrade the contract on your behalf. Consider a situation where multisigcreator.near
writes and deploys a really nice multisig fund management global contract by calling DeployPermanentContractAction
, and you (appdev.near
) would like to set up a copy of that contract for each of your app's users. Your options are:
- Most restrictive/safest:
DeployExistingContractAction(code_hash)
(or in your proposal,DeployExistingContractAction(multisigcreator.near/1)
) . Similar to normal contracts, only the account itself can replace its contract, by callingDeployExistingContractAction
again or callingDeployContractAction
. The downside of this approach is that if you need to fix a contract bug, that could be thousands and thousands of upgrades to do across each of your users' accounts. - Least restrictive/easiest: Call
DeployExistingContractAction(multisigcreator.near)
(ormultisigcreator.near/latest
from your proposal). Ifmultisigcreator.near
upgrades the global contract, all your users will automatically receive the upgrade. But it also means thatmultisigcreator.near
and not you (appdev.near
) is in control of those upgrades. - Better option: Have
appdev.near
callDeployPermanentContractAction(code)
, which will be cheap because it'll detect that the same code is already a deployed global contract from whenmultisigcreator.near
deployed it. Then your accounts useDeployExistingContractAction(appdev.near)
. That way, you leverage the nice multisig global contract, but you are in control of the upgrades for your users and can do that upgrade across your userbase in just one transaction.
I think you should be able to move from any state to any other state. In case a critical issue is found on the global contract and you have FAK for your account, you should be able to redeploy a new contract code.
@mfornet You can always deploy a new global contract to upgrade your previous global contract. But if you try to convert from global to local, then any copies on different accounts that were pointing to the latest copy of your global contract would break.
from neps.
I like this mechanism. It is fairly straightforward and seems to be a good MVP.
Processing DeployPermanentContractAction
seems to require computing a new permanent_contracts_root
, and distributing the difference from the previous root to all the validators. Will our existing implementations on how distributing state witnesses will be able to handle these types of distributions as well?
A potential future direction to consider could be that we do not eagerly download all permanent contracts to all shards / validators. Instead, a validator only fetches the permanent contract when DeployExistingContractAction
is called on an account for a contract that has not been deployed to any other account on that shard before. In order to do this, we would also potentially have to define some kind of "home" shard / validators that are guaranteed to contain the permanent contract.
from neps.
Related discussion about a more general approach to a global key-value storage: #93
from neps.
Will our existing implementations on how distributing state witnesses will be able to handle these types of distributions as well?
No it will not. The current mechanism does not distribute contract code to all validators, but only to validators assigned to that shard.
A potential future direction to consider could be that we do not eagerly download all permanent contracts to all shards / validators. Instead, a validator only fetches the permanent contract when DeployExistingContractAction is called on an account for a contract that has not been deployed to any other account on that shard before. In order to do this, we would also potentially have to define some kind of "home" shard / validators that are guaranteed to contain the permanent contract.
Complexities like "home shard" are what this design aim to simplify. If you want a smart contract to be domiciled on some shard, then you inevitably have to either complicate the state structure or deal with questions such as what if the last account with this contract deployed is deleted. The beauty of this design is that it does not make any change to the state representation and therefore avoids a number of complexities.
from neps.
This is an awesome addition! I would also want to know how upgrades are handled (and if they are possible at all under this mechanism), and if smart contracts stay upgradable, then how are storage migrations handled?
from neps.
The proposal above describes a global contract code that doesn't have any label which means there is no permissions and upgradability that have been enjoyed by NEAR smart contracts.
One option to extend proposal with:
DeployPermanentContractAction
gets executed from specific account based on permissions of that account- This generates a message that is sent to all validators, that includes the pair
(<account id>, <contract hash>)
- Any validator when receiving such message, validate that it is received from the shard that has
<account id>
and updates the global smart contract table they maintain with this pair. If there was an existing item in the registry under<account id>
, it gets replaced. - For shared smart contracts, we can have then two options: use
<contract hash>
or use<account id>
viaDeployExistingContractAction
- For sharded smart contracts, one can refer to
<account id>
which resolves to the current<contract hash>
from neps.
Given this will be the same method that will power both shared and sharded smart contracts, I think making sure that you have the account_id
management from the start will be important. For sharded smart contracts this will make a massive difference in DevX and adoption.
There is a pretty simple way to implement support this without any changes to state/contract runtime: the table with shared contracts is keyed by hash(account_id)
and DeployExistingContractAction
uses hash(account_id)
.
from neps.
There is a pretty simple way to implement support this without any changes to state/contract runtime: the table with shared contracts is keyed by hash(account_id) and DeployExistingContractAction uses hash(account_id).
I agree that it is simple. However, it does not offer the option to not have the contract be controlled by a remote account. In comparison, if you specify a contract hash, you know for sure that this will be the contract deployed on your account and only you have the permission to modify it.
from neps.
from neps.
I agree with @bowenwang1996 that simplicity is a benefit here. As a developer, I can check the code deployed, link it to my account, and know that it will never change (which removed any chance of new bugs being introduced in the future without my explicit consent)
If I need to update my contract in the future there are 3 options:
- My contract was not locked - I simply updated to the new address
- My contract was locked and I have an update function - I use it to update to the new address
- My contract was locked and with no update function - I didn't want my contract to be updatable on the first place
I would expect most contracts to not update frequently.
When I spoke with developers about this need, they were more worried about storage cost than upgradeability
With that being said, if this is a common pattern in Ethereum, we might add another layer of friction on their onboarding journey
from neps.
Adding notes from a discussion with @ewiner @alexauroradev @ilblackdragon:
- "Permanent contracts" is not necessarily the best name. Global contracts are more intuitive
- We want to have the ability of "copying" a globally deployed contract. The idea is that someone may want to "fork" an already deployed global contract and have the ability to upgrade it for those who deploy from the account that deploys the fork without affecting anyone who deploys from the original account. As an example, if "root.near" deploys a global multisig contract, "as.near" may want to fork the deployment and other people can deploy by referring to "as.near". "as.near" and "root.near" can independently update the aforementioned global contract. From a technical perspective, what this means is that a
DeployPermanentContractAction
, when processed, will burn tokens only if the contract to be deployed has not been deployed before. Otherwise it will only charge gas and there will be no storage cost associated.
from neps.
We want to have the ability of "copying" a globally deployed contract. The idea is that someone may want to "fork" an already deployed global contract and have the ability to upgrade it for those who deploy from the account that deploys the fork without affecting anyone who deploys from the original account.
I'm trying to understand the motivation. Is it this one:
Using global contracts deployed by third parties is unsafe because they can upgrade them at any time. Instead, you should first copy the contract and then reference the copy for your contracts. Is this correct?
An alternative to copy:
Every global contract deployed to an account is there forever indexed by a number. "Upgrading" the contract means pushing a new contract to the list (previous ones stay there).
Another contract can indicate that its code is either:
- none
- local (
as.near
has some local contract) - global-pinned:
root.near/42
(updatingroot.near
won't affectas.near
) - global-with-upgrades:
root.near/latest
(as.near
will use the latest deploy fromroot.near
)
You can't convert from Global to Local, i.e. if an account has called DeployExistingContractAction, it cannot call DeployContractAction.
I think you should be able to move from any state to any other state. In case a critical issue is found on the global contract and you have FAK for your account, you should be able to redeploy a new contract code.
from neps.
Related Issues (20)
- URL: https://explorer.mainnet.aurora.dev/api/eth-rpc
- Chain Signatures HOT 8
- Problems with storage staking HOT 7
- Security Policy violation Branch Protection HOT 2
- Security Policy violation SECURITY.md HOT 2
- Runtime: enable key prefix scan HOT 4
- Runtime triggers HOT 37
- Proposal for web3-compatible wallets support HOT 20
- Wrapped NEAR v2
- Privacy with Chain Signatures HOT 6
- Improvement to gas pricing and prioritization HOT 3
- Reduce storage staking price by 10x HOT 11
- On minimally volatile gas pricing
- Bounty: HOT 1
- Bounty: HOT 1
- Баунті HOT 1
- Твікс: HOT 1
- Баунті: HOT 1
- Explain what Simple Bounty template is for
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from neps.