Versioning of contracts and upgradability test#1470
Versioning of contracts and upgradability test#1470cygnusv merged 14 commits intonucypher:masterfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1470 +/- ##
==========================================
- Coverage 84.31% 84.22% -0.09%
==========================================
Files 72 72
Lines 11225 11303 +78
==========================================
+ Hits 9464 9520 +56
- Misses 1761 1783 +22
Continue to review full report at Codecov.
|
468fdc1 to
5035026
Compare
c545440 to
8458dfc
Compare
| raw_interfaces = self._compile(root_source_dir, other_source_dirs) | ||
| for name, data in raw_interfaces.items(): | ||
| # Extract contract version from docs | ||
| version_search = re.search(r'\"details\":\".*?\|(v\d+\.\d+\.\d+)\|.*?\"', data['devdoc']) |
There was a problem hiding this comment.
Can you expand this regex into the verbose format?
Example:
p = re.compile(r"""
(\+\d{1,2})? # Optional Country Code +1 or perhaps +22
(-|\()? # Optional hyphen or open parenths for the area code.
(\d{10} # Try and match ten digits exactly
| # Else
(\d{3} # Match three digits
[\-|\)]{0,2}) # Hypen or close parenths zero through 2 times (to account for -))
{2} # Repeat to match the next three digits
\d{4}) # The remaining four digits
$ # Ensure nothing else follows
""", re.VERBOSE)
| * @param _index Index of the sub stake | ||
| * @param _periods Amount of periods for extending sub stake | ||
| **/ | ||
| */ |
8458dfc to
851de8f
Compare
3c12856 to
5680bd2
Compare
| for name, data in raw_interfaces.items(): | ||
| # Extract contract version from docs | ||
| version_search = re.search(r'\"details\":\".*?\|(v\d+\.\d+\.\d+)\|.*?\"', data['devdoc']) | ||
| version_search = re.search(r""" |
| @@ -0,0 +1,144 @@ | |||
| """ | |||
There was a problem hiding this comment.
🚀 - This is a relief, good work. I think this test can be emphasized in our CI workflow by running it in its own job.
| with pytest.raises(BaseContractDeployer.ContractDeploymentError): | ||
| assert policy_manager_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED | ||
| assert not policy_manager_deployer.is_deployed | ||
| assert not policy_manager_deployer.is_deployed() |
There was a problem hiding this comment.
Is PolicyManagerDeployer.is_deployed no longer a @property method?
There was a problem hiding this comment.
I added version as parameter to this method, None by default means any version of contract
| @click.option('--retarget', '-d', help="Retarget a contract's proxy.", is_flag=True) | ||
| @click.option('--target-address', help="Recipient's checksum address for token or ownership transference.", | ||
| type=EIP55_CHECKSUM_ADDRESS) | ||
| @click.option('--ignore-deployed', help="Ignore already deployed contracts if exist.", is_flag=True) |
There was a problem hiding this comment.
return of "bare" mode? I like your name better.
There was a problem hiding this comment.
It's related to "bare" but much simpler, turns off 'is_deployed' check to redeploy same contract multiple times (first of all for test)
There was a problem hiding this comment.
Just for my own understanding: is this flag essentially a force type option to deploy the contract even if previously deployed?
There was a problem hiding this comment.
Correct, one remark - force for the same contract with the same version
There was a problem hiding this comment.
Does this have a use beyond tests?
There was a problem hiding this comment.
I see at least one use: redeploying same contract but with different constructor parameters, for example, disable/enable test mode of StakingEscrow (for worklock)
There was a problem hiding this comment.
But are we going to do that on a real deployment? because as far as I understand, the test mode is only for tests. Or are you planning on trying that on testnet?
There was a problem hiding this comment.
test mode for testnet, to change worklock
| ]) | ||
| interfaces = solidity_compiler.compile() | ||
|
|
||
| # Remove AST because id in tree node depends on compilation scope |
There was a problem hiding this comment.
Woah - can you expand a bit on this?
There was a problem hiding this comment.
Each element in AST has ID field. This value depends on scope of compiled files (all contracts). First source for SolidityCompiler includes only main contracts, second - also tests. Merging two results lead that main contracts has AST from first compilation, test contracts from the second. Interface has contracts with the same AST as in second compilation for all contracts. We don't use AST yet and main part for comparing is bytecode, so I remove it
5680bd2 to
0b92d15
Compare
derekpierre
left a comment
There was a problem hiding this comment.
🎸 - Very organized and clean! Added some comments, but I'm unsure I'm knowledgeable enough about this part of the codebase to add a meaningful approval - best for me to leave it to the dev pros 😄
| @click.option('--retarget', '-d', help="Retarget a contract's proxy.", is_flag=True) | ||
| @click.option('--target-address', help="Recipient's checksum address for token or ownership transference.", | ||
| type=EIP55_CHECKSUM_ADDRESS) | ||
| @click.option('--ignore-deployed', help="Ignore already deployed contracts if exist.", is_flag=True) |
There was a problem hiding this comment.
Just for my own understanding: is this flag essentially a force type option to deploy the contract even if previously deployed?
Co-Authored-By: Derek Pierre <derek.pierre@gmail.com>
| requested_version == 'earliest' and \ | ||
| (major < current_version_parsed[0] or | ||
| major == current_version_parsed[0] and minor < current_version_parsed[1] or | ||
| major == current_version_parsed[0] and minor == current_version_parsed[1] and patch < current_version_parsed[2]): |
There was a problem hiding this comment.
Wow, a 9-line condition. This is though!
I think this part needs some touches to improve readability. As far as I can tell, you're trying to check lexicographical ordering between tuples, which Python implements already. So, e.g., lines 667 to 669 can be changed to (major, minor, patch) > current_version_parsed; similarly, lines 671 to 673 can be changed to (major, minor, patch) < current_version_parsed
There was a problem hiding this comment.
@cygnusv That's pretty cool - didn't know you could do that.
There was a problem hiding this comment.
Thanks, really cool suggestion.
✔️
| @click.option('--retarget', '-d', help="Retarget a contract's proxy.", is_flag=True) | ||
| @click.option('--target-address', help="Recipient's checksum address for token or ownership transference.", | ||
| type=EIP55_CHECKSUM_ADDRESS) | ||
| @click.option('--ignore-deployed', help="Ignore already deployed contracts if exist.", is_flag=True) |
There was a problem hiding this comment.
Does this have a use beyond tests?
Co-Authored-By: Derek Pierre <derek.pierre@gmail.com> Co-Authored-By: David Núñez <david@nucypher.com>
6d28cb5 to
0473812
Compare
.circleci/config.yml
Outdated
| - run: | ||
| name: Ethereum Contract Upgradeability Test | ||
| command: | | ||
| pytest $(circleci tests glob "tests/blockchain/eth/contracts/test_contracts_upgradeability.py" | circleci tests split --split-by=timings) |
There was a problem hiding this comment.
After checking the performance of the CI build, I think having a separate job for this test is unnecessary. It blocks a CI box for some time, while if it were included in the contracts job, it will probably be executed without any overhead due to current parallelism.
There was a problem hiding this comment.
The main reason for extracting was readability of test results, like in 1459, where only one contract test failed, I like how it looks
There was a problem hiding this comment.
Right, I understand, but we have a limited number of CI boxes and using one of them for a single test that runs for 21 seconds doesn't seem a good idea to me.
There was a problem hiding this comment.
makes sense, I'll change it back
| for name, data in raw_interfaces.items(): | ||
| # Extract contract version from docs | ||
| version_search = re.search(r'\"details\":\".*?\|(v\d+\.\d+\.\d+)\|.*?\"', data['devdoc']) | ||
| version_search = re.search(r""" |
| /** | ||
| * @notice Contract for calculate issued tokens | ||
| **/ | ||
| * @dev |v1.1.2| |
There was a problem hiding this comment.
What about considering v.1.1.1 for all contracts?
There was a problem hiding this comment.
I just tried to remember how many changes we did before, but really it doesn't matter because of testnet redeploy and new versions v2.1.1
| @property | ||
| def is_deployed(self) -> bool: | ||
| return bool(self._contract is not CONTRACT_NOT_DEPLOYED) | ||
|
|
There was a problem hiding this comment.
Yes! I had a very similar change in a WIP PR. This property was just checking if the contract was deployed with that very same instance of the deployer, which of course is not very useful in use cases like upgrades or rollbacks. Glad this is changed :)
…move parameters from constructor in deployers (overrides)
Co-Authored-By: Derek Pierre <derek.pierre@gmail.com> Co-Authored-By: David Núñez <david@nucypher.com>
0473812 to
4dcb5b2
Compare
Closes #1464
Closes #1465
@dev), for example|v1.2.3|SolidityCompilerVersion format is
|vi.j.k|, wherei- fork (I hope will be always1),j- upgradeable signature/state changes,k- small changes inside existent function