Skip to content
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

Revisit gas costs of having Crowdsale deploy the token itself #358

Closed
frangio opened this issue Aug 11, 2017 · 24 comments · Fixed by #690
Closed

Revisit gas costs of having Crowdsale deploy the token itself #358

frangio opened this issue Aug 11, 2017 · 24 comments · Fixed by #690
Assignees

Comments

@frangio
Copy link
Contributor

frangio commented Aug 11, 2017

The bytecode that results from having Crowdsale deploy the token itself is too big and causes the deployment to be too costly.

Related to #351. Should be fixed the same way.

@aohua
Copy link

aohua commented Aug 12, 2017

I'm having the same issue when deploy the sample crowdsale code to Ropsten, even it fails, still costing me 0.5 ether for gas. How did you guys solve this issue?

@frangio
Copy link
Contributor Author

frangio commented Aug 12, 2017

Setting the truffle gas limits manually. @spalladino maybe remembers the exact parameters we used.

@spalladino
Copy link
Contributor

spalladino commented Aug 12, 2017 via email

@vinniejames
Copy link

I'm having the same/similar problem. I cannot deploy the SampleCrowdsale. Im attempting on Ropsten, using Remix, and passing in these parameters to "Create" for SampleCrowdsale(300, 172800, 1000, 20, 30, "0xADDRESS") Is there a way to deploy this? I've tried increasing the gas limit super high in Remix, no such luck callback contain no result Gas required exceeds block gas limit: 300000000

@zono
Copy link

zono commented Sep 8, 2017

I'm also having the same/similar problem. I posted about it to stackexchange. I'd appreciate it if you could help me.

https://ethereum.stackexchange.com/questions/26012/is-it-possible-to-divide-my-crowdsale-contract-into-multiple-files-in-order-to-s

@gundas
Copy link

gundas commented Sep 8, 2017

I think the error might be caused by the constructor arguments (not be excessive use of gas) - the first and second Crowdsale constructor arguments are timestamps, not block numbers. Probably the first check throws:

function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) {
    require(_startTime >= now);

@zono
Copy link

zono commented Sep 8, 2017

Thanks! @gundas As you mentioned, I could deploy it after change to timestamp. I'm sorry please forget my issue. I updated my stackexchange post.

@tomericco
Copy link

I keep getting this error while trying to deploy Crowdsale contract to ropsten network:
Error: The contract code couldn't be stored, please check your gas amount.
The last block gas limit is 6993557, so I set the gas limit to 6990000 in truffle configurations. I struggle to find what's wrong.

BTW, I use timestamps for the first constructor arguments, as @gundas mentioned.

@spalladino
Copy link
Contributor

@tomericco keep in mind that that error is also thrown when there is an error during the constructor execution, and may actually be unrelated to the gas amount. Make sure you are not breaking any precondition of the Crowdsale constructor, such as timestamps needing to be in the future, with start less than end.

@tomericco
Copy link

@spalladino Here is my Truffle deployment script:

const Crowdsale = artifacts.require('zeppelin-solidity/contracts/crowdsale/Crowdsale.sol');

module.exports = function(deployer, network, accounts) {
    const startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + 1;
    const endTime = startTime + (86400 * 30); // 30 days
    const ethRate = new web3.BigNumber(1000);
    const wallet = accounts[0];

    deployer.deploy(Crowdsale, startTime, endTime, ethRate, wallet);
};

Do you see anything suspicious?

@spalladino
Copy link
Contributor

spalladino commented Oct 10, 2017 via email

@tomericco
Copy link

It works now. This is why it worked on the local TestRPC, and not on Ropsten.
Thanks a lot @spalladino!

@amazingandyyy
Copy link
Contributor

my setting

rinkeby: {
      host: 'localhost',
      port: 8545,
      network_id: 4,
      gas: 6000000
    }

and set const startTime = latestTime() + duration.seconds(120); // + immediately
it works! :) thanks for everyone's help

@MISCPLATFORM
Copy link

This is driving me crazy, i now get a different error.

Using network 'ropsten'.

Running migration: 1_initial_migration.js
Deploying Migrations...
Error encountered, bailing. Network state unknown. Review successful transactions manually.
undefined

@spalladino spalladino added next and removed backlog labels Jan 15, 2018
@spalladino
Copy link
Contributor

Moving to next due to high costs reported, as discussed today by @maraoz

@spalladino
Copy link
Contributor

I've been playing around a bit with removing the token creation from the crowdsale contract, and requiring it as a parameter. The code change would be the following:

-  function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) public {
+  function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet, MintableToken _token) public {
     require(_startTime >= now);
     require(_endTime >= _startTime);
     require(_rate > 0);
     require(_wallet != address(0));
 
-    token = createTokenContract();
+    token = _token;
     startTime = _startTime;
     endTime = _endTime;
     rate = _rate;
     wallet = _wallet;
   }
 
-  // creates the token to be sold.
-  // override this method to have crowdsale of a specific mintable token.
-  function createTokenContract() internal returns (MintableToken) {
-    return new MintableToken();
-  }

The gas costs for the current implementation with the embedded token contract code, vs this new implementation with the token as a parameter, with the solc optimizer on and off, are the following:

Version Optimized Not optimized
Embedded token 1872055 3629854
As a parameter 757040 + 426098 1562529 + 564671
Gas savings 688917 1502654

The costs of deploying the mintable token and then the sale are shown separately as the two addends in each cell. The cost of the transfer ownership is missing, though it is negligible (~30K in a not optimized version).

The code I used for testing both versions was the following:

// Current version
ts = web3.eth.getBlock('latest').timestamp
Crowdsale.new(ts + 100, ts + 1000, 1000, 0x1).then(c => sale = c)
t = web3.eth.getTransaction(sale.transactionHash)
web3.eth.estimateGas({from: web3.eth.accounts[0], to: 0x0, data: t.input})

// New version
MintableToken.new().then(m => token = m)
web3.eth.estimateGas({from: web3.eth.accounts[0], to: 0x0, data: web3.eth.getTransaction(token.transactionHash).input})
ts = web3.eth.getBlock('latest').timestamp
Crowdsale.new(ts + 100, ts + 1000, 1000, 0x1, token.address).then(c => sale = c)
web3.eth.estimateGas({from: web3.eth.accounts[0], to: 0x0, data: web3.eth.getTransaction(sale.transactionHash).input})

I think we have enough arguments to move the token creation outside of the crowdsale contract, right?

@maraoz
Copy link
Contributor

maraoz commented Jan 18, 2018

ACK, nice work @spalladino! :)

spalladino added a commit to spalladino/openzeppelin-contracts that referenced this issue Jan 18, 2018
@spalladino spalladino self-assigned this Jan 18, 2018
@spalladino spalladino added review and removed backlog labels Jan 18, 2018
spalladino added a commit to spalladino/openzeppelin-contracts that referenced this issue Jan 18, 2018
@frangio frangio removed the review label Jan 24, 2018
@gururise
Copy link

Do you have an example of how one would call the transferOwnership() function on the token in the 2_deploy_contracts.js file to be able to use this new functionality?

@spalladino
Copy link
Contributor

@gururise sure, check out the setup step in the tests with this new feature:

    let token = await MintableToken.new();
    let crowdsale = await Crowdsale.new(startTime, endTime, rate, wallet, token.address);
    await token.transferOwnership(crowdsale.address);

@tombenj
Copy link

tombenj commented Jan 27, 2018

Getting the error:

  Deploying XrrCrowdsale...
  ... 0x2a0bb70940abbbd44c9e953fbccef77a732aaf84bb0dd2e534790853416d64aa
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: VM Exception while processing transaction: revert
    at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:41483:16)
    at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:330353:36
    at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:176198:11
    at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:326008:9
    at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:329052:7)
    at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176427:18)
    at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176717:12)
    at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176872:12)
    at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176832:24)
    at emitNone (events.js:110:20)

Using @tomericco code with seconds modification:

module.exports = function(deployer, network, accounts) {
    const startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + 100;
    const endTime = startTime + (86400 * 30); // 30 days
    const ethRate = new web3.BigNumber(1000);
    const wallet = accounts[0];

    deployer.deploy(Crowdsale, startTime, endTime, ethRate, wallet);
};

All the suggestions above don't work including @amazingandyyy latestTime whice results in:

ReferenceError: latestTime is not defined
    at module.exports (/Users/tomgolan/contract/migrations/2_deploy_contracts.js:12:21)
    at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:176055:7
    at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:203303:7
    at tryToString (fs.js:514:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:502:12)

Edit:

Managed to import latestime and duration from the tests helpers but still getting the same error:

Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: VM Exception while processing transaction: revert

@spalladino
Copy link
Contributor

@propercoil maybe try increasing the number of seconds for startTime from +100 to something much larger, just to rule that one out?

@tombenj
Copy link

tombenj commented Jan 30, 2018

@spalladino it wasn't that. I was looking at master when my repo was on the release. Turned out to be a missed constructor param. Need to remember that a revert can be caused from many things.

@shaharsol
Copy link

@spalladino your answer to @tomericco solved me a several days lasting frustration!

@itoonx
Copy link

itoonx commented Apr 18, 2018

@spalladino Nice changes !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.