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(mixin-ownable): add Ownable mixin and tests #1305
Conversation
da25ec6
to
2e5d552
Compare
Codecov Report
@@ Coverage Diff @@
## master #1305 +/- ##
=========================================
+ Coverage 64.74% 64.8% +0.05%
=========================================
Files 1529 1529
Lines 40396 40396
Branches 3941 3941
=========================================
+ Hits 26156 26179 +23
+ Misses 14240 14217 -23
|
Codecov Report
@@ Coverage Diff @@
## master #1305 +/- ##
==========================================
+ Coverage 62.23% 64.79% +2.56%
==========================================
Files 1529 1529
Lines 40393 40407 +14
Branches 3940 3943 +3
==========================================
+ Hits 25137 26183 +1046
+ Misses 15256 14224 -1032
|
2e5d552
to
765fb3e
Compare
80a5837
to
6c69293
Compare
6c69293
to
2669607
Compare
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.
overall lgtm
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Show resolved
Hide resolved
202cf86
to
9f7469d
Compare
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.
LG, just two last comments.
packages/neo-one-smart-contract-lib/src/__tests__/ownership/TestOwnableContract.test.ts
Outdated
Show resolved
Hide resolved
d809969
to
7c47d5b
Compare
7c47d5b
to
a747bc6
Compare
a747bc6
to
a704306
Compare
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.
One last comment!
@@ -0,0 +1,57 @@ | |||
import { Address, SmartContract, createEventNotifier } from '@neo-one/smart-contract'; | |||
|
|||
const notifyTransferOwnership = createEventNotifier<Address | undefined, Address>('transfer_ownership', 'from', 'to'); |
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.
the from
Address
can never be undefined
, no?
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.
@dicarlo2 True, now, after modifying transferOwnership
to use ownerOrThrow
otherwise, the mutableOwner
as passed is possibly undefined
.
Which path should these functions go? extra cpu cycles, or fewer with that optional undefined?
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.
Answer discussed @ standup, going with "Easy to read".
} | ||
|
||
protected onlyOwner() { | ||
if (this.mutableOwner !== undefined && !Address.isCaller(this.mutableOwner)) { |
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 should be using this.ownerOrThrow
no? Seems like a bug - if there's no owner then this should throw I think.
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.
@dicarlo2 "bug" might be a little harsh, I'd say mine is between 4 and 12 operations more efficient and achieves same goal. I can switch it to ownerOrThrow()
if you still like.
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 think he is suggesting something like:
protected onlyOwner() {
if (!Address.isCaller(this.ownerOrThrow())) {
throw new Error('not owner');
}
}
(edit because assignment)
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.
(because if this.mutableOwner
is undefined then this will pass always)
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.
@danwbyrne yes, that was my glitch the !==undefined. But: re discussion during standup, we are favoring code readability over scrutinizing nominal amounts of gas for extra stack operations. Change will be made, thank you!
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.
hmmm, what is the order that these PRs need to go in? I'm starting to get lost by them :P
This one first. |
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 see now this is the first one that needs to go in :)
} | ||
|
||
protected onlyOwner() { | ||
if (this.mutableOwner !== undefined && !Address.isCaller(this.mutableOwner)) { |
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 think he is suggesting something like:
protected onlyOwner() {
if (!Address.isCaller(this.ownerOrThrow())) {
throw new Error('not owner');
}
}
(edit because assignment)
} | ||
|
||
protected onlyOwner() { | ||
if (this.mutableOwner !== undefined && !Address.isCaller(this.mutableOwner)) { |
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.
(because if this.mutableOwner
is undefined then this will pass always)
a704306
to
6f55ea7
Compare
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.
just fix the deepscan
@danwbyrne Unrelated |
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.
lgtm.
The deepscan issues are odd, I wonder why they showed up on this PR.
bors r+ |
1305: feat(mixin-ownable): add Ownable mixin and tests r=dicarlo2 a=davemneo # Overview This class provides a means to assign an address as the owner of a contract. Extending this class and adding ` this.ownerOnly(); ` to the beginning of all public functions will throw an error anytime an address other than the primary makes requests. ## API ### Public `owner()` - returns the current owner address or undefined. ##### Manage contract Ownership with... `renounceOwnership()` - Allows only the owner to contract to become ownerless, this will cause all `ownerOnly()` calls to fail, this is not reversible. Note: the `initialOwner` will maintain still contain the initial address. `transferOwnership()` - Only the owner may transfer ownership to a new ### Internal `ownerOrThrow()` - returns the current owner address or throws an error. `onlyOwner()` - if the owner address did not call this contract an error is thrown. ### Published Events: `tokensPurchased` with purchaser, beneficiary and amount of tokens bought. ## Configuration: Be sure that any contract extending this `Ownable` mix-in sets the `initialOwner` thusly: ``` typescript: export class MyContract extends Ownable(SmartContract) { public constructor(protected readonly initialOwner = Deploy.senderAddress) { super(); } // .... awesome smart contract code ... } ``` ## Tests yarn jest TestOwnable Co-authored-by: Dave M <david.mathiesen@neotracker.io>
Overview
This class provides a means to assign an address as the owner of a contract. Extending this class and adding
this.ownerOnly();
to the beginning of all public functions will throw an error anytime an address other than the primary makes requests.API
Public
owner()
- returns the current owner address or undefined.Manage contract Ownership with...
renounceOwnership()
- Allows only the owner to contract to become ownerless, this will cause allownerOnly()
calls to fail, this is not reversible. Note: theinitialOwner
will maintain still contain the initial address.transferOwnership()
- Only the owner may transfer ownership to a newInternal
ownerOrThrow()
- returns the current owner address or throws an error.onlyOwner()
- if the owner address did not call this contract an error is thrown.Published Events:
tokensPurchased
with purchaser, beneficiary and amount of tokens bought.Configuration:
Be sure that any contract extending this
Ownable
mix-in sets theinitialOwner
thusly:Tests