-
Notifications
You must be signed in to change notification settings - Fork 11.8k
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
fix: force RefundableCrowdsale to also be a PostDeliveryCrowdsale #927
Conversation
Any reason why ci is reporting failure? logs look happy |
It's the linting:
I've been confused by this before. Maybe linting should run as a separate job? |
nice, thanks; looks like I didn't actually run that link command like the checkbox says I did 😅 |
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 smart contracts look good. I'm not convinced by the way the PostDelivery
behavior was implemented, parameterizing by the endCrowdsale
procedure.
I left some concrete ideas.
const rate = new BigNumber(1); | ||
const goal = ether(50); | ||
const lessThanGoal = ether(45); | ||
const tokenSupply = new BigNumber('1e22'); | ||
|
||
before(async function () { | ||
beforeEach(async function () { | ||
// Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache | ||
await advanceBlock(); |
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 I prefer having this in a before
block as it was before if that's all that's strictly necessary.
Actually, can you check if removing this line makes the tests fail? I feel like it was a Ganache bug that may have been fixed by now.
|
||
context('after end', function () { | ||
beforeEach(async function () { | ||
await endCrowdsale.call(this, investor, purchaser, value); |
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 a couple issues here.
endCrowdsale
is actually a function with no arguments which wraps each test's this.endCrowdsale
. So, these parameters (investor
, etc.) are never used. I think it's reasonable to expect the endCrowdsale
function to not need the parameters because the behavior itself receives them from there.
I don't think it's necessary or okay to receive endCrowdsale
as a behavior argument; the behavior should just access this.endCrowdsale
directly. Refundable
's has a boolean parameter but it should have an appropriate default value so that this works, which should be true
in this case.
await increaseTimeTo(this.openingTime); | ||
await this.crowdsale.buyTokens(investor, { value, from: purchaser }); | ||
await this.crowdsale.buyTokens(otherInvestor, { | ||
value: goalReached ? goal.minus(value) : lessThanGoal, |
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.
lessThanGoal
was meant to be used "by itself", not together with another investment of value
, so it's kind of a coincidence that value + lessThanGoal < goal
.
Maybe don't do this second investment at all if goalReached == true
?
}; | ||
}); | ||
|
||
shouldBePostDeliveryCrowdsale(investor, purchaser, value, async function () { |
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.
What about removing this.endCrowdsale
altogether and using goal
instead of value
here? I think this communicates the idea that: this should behave exactly like a PostDeliveryCrowdsale
as long as the money invested is at least goal
. It's not ideal because it wouldn't be testing a scenario where the goal is reached by more than one investment. But I'm not convinced by this.endCrowdsale
.
@frangio @shrugs If the issue is that users can transfer their tokens before the end, is it not better to force using an ERC20 token with a RBAC on who is enabled to transfer? For instance adding a
I can build this token. |
That's another fine approach. The difference is that with a post delivery crowdsale the logic is in the crowdsale and not the token contract. @frangio which approach do you like more? |
My concern with forcing a post delivery is that investors should be able to make a transaction to the If So, if it is not strictly necessary (as developer and I think also as business developer), I would prefer to build the logic when I build the token and not to force people to understand how to use ABIs. |
Fixes #877
🚀 Description
When participating in a refundable crowdsale, because tokens were delivered immediately, malicious investors could previously sell tokens to unsuspecting users and then collect their own ether-based refund after the goal is not met.
This change forces RefundableCrowdsale to also be a PostDeliveryCrowdsale where users are only allowed to withdraw tokens if the goal is reached, the crowdsale is over, and it is finalized.
npm run lint:all:fix
).