-
Notifications
You must be signed in to change notification settings - Fork 1
Conversation
I smuggled also some typing and utils refactoring.
That was a lot of work. Added 2210 and removed 401 lines of code (excluding JSON ABI files), 237 unit/integration tests, not counting 192 skipped tests due to base class tests duplication. Commits are decently organized, however I suggest reviewing it in final form. |
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.
Impressive work!
- I couldn't find anything wrong with the contracts. I will take a look at them once again tomorrow to double check.
- It looks like you have found a nice solution to tests with parametrized contexts. Also the tests are very comprehensive.
- Naming of the classes / instances related to the commands was a bit confusing for me on the first read, I've suggested some improvements (hopefully), although the general concept is neat.
- Most of the comments are just minor remarks related mostly to naming, I couldn't find anything wrong here.
contracts/MultiSig/MultiSig.sol
Outdated
} | ||
|
||
/* solhint-disable no-empty-blocks */ | ||
function() public payable {} |
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.
Maybe it makes sense to have a Deposit event here?
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.
Good suggestion. I had it initially but removed it due to doubts about "Deposit" naming in context of TipsWallet. Nonetheless, it should exist in the MultiSig base contract if we want it to be practical and used in other contexts.
Added it in commit 6b9525a.
contracts/MultiSig/MultiSig.sol
Outdated
/* solhint-disable no-empty-blocks */ | ||
|
||
function listOwners() public view returns (address[]) { | ||
return owners; |
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.
address
is public but it has a getter. It should be made private than.
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 did it consciously. owners
default getter works with indices and returns a single address at given index. So it is a separate use case. I am not sure whether the default getter is useful, I have mixed feelings about default getters for arrays in Solidity. But I thought it wouldn't hurt to leave it as it is.
bytes data | ||
) | ||
public | ||
onlySigned(v, r, s, keccak256(byte(0x19), byte(0), this, destination, value, data, nonce)) |
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.
So, where does 0x19 and byte(0) come from?
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.
It follows ERC191 specification (ethereum/EIPs#191).
0x19 <1 byte version> <version specific data> <data to sign>
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.
Good to know that, thanks
|
||
contract RecoverableMultiSig is TransferableMultiSig { | ||
|
||
uint256 public recoveryConfirmations; |
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.
This name is a bit misleading, maybe recoveryBlockOffset
?
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.
Fixed in 5bbc32b
import "./TransferableMultiSig.sol"; | ||
|
||
|
||
contract RecoverableMultiSig is TransferableMultiSig { |
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.
Am I correct that RecoverableMultiSig
does not depend on TransferableMultiSig
but just MultiSig
?
I'm just asking, this is still just fine for our use case.
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.
Yes, you are correct. I flattened it in e3af2c4.
Subconsciously I was worried about Diamond Problem in multiple base classes inheritance, but it is non-existent in Solidity.
); | ||
|
||
contract('TransferableMultiSigContract', accounts => { | ||
describe.skip('#ctor', () => { |
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.
skip
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.
Skip usage already commented in other place
|
||
const ownerSets = [[accounts[2]], accounts.slice(1, 3), accounts.slice(2, 6)]; | ||
ownerSets.map(owners => { | ||
context.skip(`When wallet has ${owners.length} owners`, () => { |
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.
skip
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.
Skip usage already commented in other place
}); | ||
|
||
describe('#ctor', () => { | ||
it('should set owners', async () => { |
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.
set -> list
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.
Fixed in 748887e
test/tipswallet.test.ts
Outdated
}); | ||
|
||
describe('#ctor', () => { | ||
it('should set owners', async () => { |
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.
list
. This is duplicated, it can be extracted to a testListOwners(ctx)
method
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.
Fixed in 748887e
const artifacts: SignHashArtifacts; | ||
const assert: Chai.AssertStatic; | ||
const contract: ContractContextDefinition; | ||
} |
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 not sure why have you removed that.
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.
There are two problems with this approach:
Not in all contexts these variables are defined (e.g. seed)
WebStorm does not recognize them (pretty lousy argument, but I heavily rely on this IDE)
@biern Thanks for a thorough review. I fixed all the things you pointed out except the declaration of global variables. I will reconsider changing it when WebStorm supports it. But still, there is an issue that not in all context these variables are available (for example in custom scripts, |
I've took a look at the contracts again today and still couldn't find any issues. Outstanding job, I'm merging this. |
Closes #23
Replaces #29 with more concise and future-proof implementation.
Checklist: