Closed hiddentao closed 2 years ago
I could do with help on the calculations, particularly the divisions, since I'm not an expert and I know that floating point isn't really supported.
Would it be possible to submit a refund address at the time you make your contribution? Or, would that make things too unwieldy/expensive?
The other drawback of this approach is that it increases the concentration of funds until the refund is issued, and so increases incentive to attack any vulnerabilities of the contract, but given the typical sizes of these crowdsales the incentive is high already.
However in my view it is essential and no reason for all sales not to use this or something similar once battle tested.
Instead of refunding 100%, burn a percentage of the returned funds to discourage monopoly-sized bids. In Scenario 2, A monopolizes the supply, but their risk exposure is capped by the ICO; they put in a big bid, own 95% of tokens with half their bid back.
Burning a percentage of the refund proportional to their percent ICO ownership would only encourage a large volume of small bids, indicating a fixed burn rate might be apropos?
Instead of refunding 100%, burn a percentage of the returned funds to discourage monopoly-sized bids. In Scenario 2, A monopolizes the supply, but their risk exposure is capped by the ICO; they put in a big bid, own 95% of tokens with half their bid back.
Burning a percentage of the refund proportional to their percent ICO ownership would only encourage a large volume of small bids, indicating a fixed burn rate might be apropos?
+1
Let's:
EDIT to add:
EDIT again to add:
For email-only readers, edited my previous comment to add:
@joelcan That could be possible, though what additional advantage does that give?
@plutoegg Point noted, though additional measures to deal with that will ironically increase code complexity again.
@pmbauer @taoeffect I like the idea of penalizing excess contributions in some way, though if we opt for burning then even small contributors will lose their ETH, which one may argue unfairly penalizes them. Of course, perhaps a minimum threshold can be set, i.e. only if you contribute over a certain level of ETH will some of your excess get burned.
Another thought I had was to implement logarithmic scaling of contributions. For example:
1 eth = 1 token, for example. 9 eth = 1 token 10 eth = 1 token 11 eth = (10/10) + 1 = 2 tokens 21 eth = (20/10) + 1 = 3 tokens 99 eth = (90/10) + 1 = 10 tokens 154 eth = (100/100) + (50/10) + 4 = 10 tokens 5234 eth = (5 + 2 + 3 + 1) = 11 tokens
The idea would be to lessen the impact of larger contributions.
The whale still wins big, but the impact has been lessened. In the non-log contract above the whale would get 99.999%, leaving the small buyer with virtually nothing.
Edit: one concern is the cost of doing the log-scaling calculations.
@hiddentao The logarithmic scaling does not work because contributors could again create multiple addresses and contribute a small amount with each and thus get more tokens as if when they would contribute all at once. Same goes for the threshold burning approach (multiple addresses all contributing under threshold)
Is this EIP material? EIPs are relevant for standardising things that multiple implementations need to interoperate with, which doesn't seem the case here. I'd highly recommend creating a repo for this, with implementation, tests, and discussion there.
@tawaren The idea is that it's far more expensive for a contributor to put in large amounts. Without a way of knowing who actually owns a given address it's not possible to have a scheme where each person/entity is restricted to a certain amount of tokens.
@Arachnid Agreed, I've actually made a start over at https://github.com/hiddentao/ethereum-token-sales.
this might be fair but fair isnt what drives the tokensale frenzy
@hiddentao I'm currently working on something similar with stretch-goals. The leftover (above certain amount) gets send to charity address (hard coded).
Ad calculations: I'm currently using this:
function toPercentage (uint256 total, uint256 part) internal returns (uint256) {
return (part*100)/total;
}
function fromPercentage(uint256 value, uint256 percentage) internal returns (uint256) {
return (value*percentage)/100;
}
100 as dividing on full percent seems fair to me, but you could go event further by just adding more zeros to both functions.
I'm using two functions instead of just one because I'm recalculating the rate in USD (using Oraclize) instead of ethers as it seems to be easier for participants to read.
can u merge it to one file so i can launch in mist wallet ?
@gaitchs That's pretty easy to do, just replace the following lines:
import "./StandardToken.sol";
import "./SafeMath.sol";
With the actual contents of those files.
Is there any known ICO that used/is using this approach?
What do u mean
On 06-Jan-2018 6:26 PM, "Anthony Akentiev" notifications@github.com wrote:
Is there any known ICO that used/is using this approach?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ethereum/EIPs/issues/642#issuecomment-355745297, or mute the thread https://github.com/notifications/unsubscribe-auth/AVeKiq2_1UBFsJpwY9QB9ZOUdEHp4-crks5tH22QgaJpZM4Ns6MC .
@gaitchs I mean that is there any project already that wants to use this approach (that is of course still "in development")?
I am categorising ICO models in this doc -https://docs.google.com/document/d/1hnMjwaaYUZGch-rprvAtqay9e_ivePCpezBY5ywrrKE/edit?usp=sharing
I've already added the "Proportional Refund Model" to it.
@hiddentao Do you want me to mention you in my doc? Btw, you can help me and add your text/comments to the document! Your feedback will be highly appreciated. Thx
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.
Preamble
Simple Summary
A contract which allows for a fairer crowdsale through proportional allocation rather than first-come-first-served.
Abstract
This ERC-20 derived token contract aims to avoid a recurring problem in popular ICO/crowdsales, whereby a small no. of participants can effectively obtain all available tokens via a combination of extremely high transaction fees (unaffordable to most participants) and "getting there first". An acute example of this problem is the recent BAT tokensale, where all tokens were allocated within 24 seconds.
Although the ICO holder's goals of raising funding are met in such situations, the fact that the majority of tokens are in the hands of relatively few players is less than ideal when considered from the perspective of decentralisation. The recurring nature of this issue has led to a race-to-be-the-fastest, causing massive network congestion due to the large volume of transactions which are created in such a short space of time.
Some solutions have been proposed, including:
Capping no. of tokens per address - The problem with this is that a participant could just create multiple addresses to send from. Similar potential "solutions" such as rate-limiting have similar issues associated with them.
Using web-based systems to authenticate the participant and their corresponding address separately - this requires more work on the part of the sale organiser. It could introduce more bugs in the process, and will thus require more testing. It also increases the work a contributor must do in order to participate (not to mention tying their identity of some sort to their contribution), which some may argue goes against the "ethos" of the system as a whole.
This ERC proposes a token contract to solve these issues without limiting how much Ether a participant can contribute. Specifically:
Tokens are proportionally allocated according to amount contributed. Being early or late to the game has no impact on the no. of tokens a participant receives. Every contributor will recieve some tokens, but larger contributors still get to benefit from having contributed more. Since there is no limit to contributions, any excess ETH (calculated once sale is complete) will be refunded to contributors and only the ETH required to meet the target funding level will be retained.
Price per token is still predictable. All that has changed is that a given participant may not get exactly as many tokens as they are hoping for since the calculation is now proportional. However, by contributing more ETH each participant can increase the proportion of the total no. of tokens number of tokens they receive, thus still incentivising contributions.
Sale will run the full duration. Because tokens are only allocated once the sale is complete, the sale will run its full duration, giving plenty of time for contributions to come in. No more network congestion.
Sale organiser and participants can finalize independently of each other. One the sale is complete, a contributor can at any time call into the contract to either obtain a full refund (if the sale failed to raise the target funding level) or claim their tokens (if the sale did raise at least the target funding level). The sale organizer can call in to ensure the raised funding gets sent to the deposit address. Once the sale is complete, neither party has to wait for the other in order to proceed with these actions.
Drawbacks of this approach:
Example
Target ETH to raise = 100 ETH Total supply of tokens = 100 tokens
Scenario 1
Scenario 2
Specification
Methods
function contribute() payable
- Contribute ETH to the crowdsale.function finalizeFunding()
- Put funding into deposit address once sale is over.function claimTokensAndRefund()
- Claim tokens and/or get a refund once sale is done.Events
event CreateFairToken(string _name)
- Triggered when contract is deployed in the chain.event Contribute(address _sender, uint256 _value)
- Received a contribution.event FinalizeSale(address _sender)
- Sale finalized, funding send to deposit address.event RefundContribution(address _sender, uint256 _value)
- Contribution refunded.event ClaimTokens(address _sender, uint256 _value)
- Tokens claimed and excess ETH refunded.Example Implementation
This uses StandardContract.sol and SafeMath.sol.
Initially I didn't think the price-per-token was going to be the same for every user which is why I didn't store the
tokens per ETH
in the contract but just the target ETH funding level instead. But the contract could be rewritten to store tokens per ETH instead and base the calculations on that.Copyright
Copyright and related rights waived via CC0.
_(Credit to u/pa7x1 for the initial idea behind this approach)._