Solvedopenzeppelin contracts Revisit gas costs of having Crowdsale deploy the token itself

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.

25 Answers

✔️Accepted Answer

Other Answers:

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 + 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 => 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 + 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?

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);

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

Related Issues:

openzeppelin contracts Support for Solidity 0.7.0
Support for Solidity 0.7 has been published in a specially tagged release @openzeppelin/contracts@3....
openzeppelin contracts Revisit gas costs of having Crowdsale deploy the token itself
Yup startTime is not enough in the future You are using 1 second after the timestamp of the current ...
go ethereum Unable to attach
Apparently on Windows we now have to specify the IPC path and it was not necessary in Geth 1.7.3: ge...
web3.js sendSignedTransaction() error: invalid sender
@paulrberg If you want to use the version: 2.0.0 you should add extra parameter chain like this ...
web3.js The method personal_unlockAccount does not exist/is not available
@vijayr2410 Well Looks like it's just require to specify following parameters to resolve this issue ...
web3.js Handle web socket disconnects
You can listen to events from the WebSocketProvider to detect disconnects. Im making an app that mon...
go ethereum Vendoring fails on projects using the native Golang bindings
A temporary solution is to just manually copy the files into vendor: System information Expected beh...
truffle Compile Error
truffle compile --all This works [x ] I've asked for help in the Truffle Gitter before filing this i...
truffle ParserError: Expected identifier, got 'LParen' for emit and constructor parameters
@satyamakgec Could you see if this fixes the global installation for you? I've asked for help in the...
web3.js Transferring ERC20 tokens from account using web3 over Ropsten
Single-address allocation of MineFIL Token (MFIL) code which was written and tested using web3 versi...
web3.js Error: Can't resolve 'crypto'
Ah yes!! this solution with the patch worked:
web3.js Truffle and Ganache providers, Metamask Provider Engine no longer accepted as valid by web3
For those who might not know me I'm part of the Truffle team and @davidmurdoch and I oversee the dev...
truffle Can't compile contracts due to 'module' is undefined
If you have the same issue on Windows instead of truffle compile try truffle.cmd compile ...
go ethereum eth.getBlock("latest").number is always 0
Syncing Ethereum is a pain point for many people so I'll try to detail what's happening behind the s...
truffle Not usable on Node.js 12
Hey everyone! ✋ We just published an experimental prerelease that uses a fork of mocha with one tiny...
truffle Error encountered, bailing. Network state unknown. Gas is 4700000
It seems that gas and gasPrice from truffle.js are not getting passed to TestRPC anymore though I do...
ethers.js Invalid ENS name error when a signer is used instead of an address
Example problematic code: Yields confusing error: Fix: I guess extra confusing for typescript users ...
web3.js Transaction was not mined within 50 blocks, please make sure your transaction was properly send. Be aware that it might still be mined!
I think I found the error When I call a contract function and await the send startWatching is invoke...
truffle permission denied, open '/root/.config/truffle/config.json'
The solution at this URL worked for me Back up your computer On the command line in your home direct...
truffle Error: *** Deployment Failed *** "Migrations" -- invalid sender.
Obviously it is caused by hdwallet-provider just switch hdwallet-provider back to 1.2.2 It looks lik...
ethers.js Feature: better historical event API
So for a few examples (which I agree I really like the library but I spent an hour trying to figure ...
hardhat allowUnlimitedContractSize doesn't work for deployments within Solidity
@ztcrypto I had this similar issue as of now too Make sure to also include blockGasLimit: 0x1fffffff...
web3.js Angular hack with node: {crypto: true} doesn't work anymore in Angular 12
@NicolasKritter Thanks for sharing your solution I've fixed the process and Buffer errors the way yo...
ccxt Binance error: Timestamp for this request was 1000ms ahead of the server's time.
@jasonmellone I just synched my clock Unfortunately just synching the clock does not work ...
ethers.js Contract with function overloading
If you are using function overloading the first definition gets the bare name You will need to speci...
web3.js Unable to install web3 1.0.0-beta.11 or web3 1.0.0-beta.12
@1337cookie try installing v0.20.0 or downgrading node to v6: or Hi I'm using node 8.2.1 and npm 5.3...
web3.js Unable to install web3 on windows10
$npm install web3@^0.20.0 worked for me Issue solved on #950 C:>npm install -g web3 web3@1.0.0-beta....
go ethereum Synchronisation failed "retrieved hash chain is invalid"
Apparently there is data missing from your database This can happen if your PC was shut down abruptl...
go ethereum Unable to attach to the local running geth node
On MacOS for testnet: geth attach ipc:/Users/ekotysh/Library/Ethereum/testnet/geth.ipc ...
web3.js web3.currentProvider.sendAsync is undefined
try to add before create new instance: Web3.providers.HttpProvider.prototype.sendAsync = Web3.provid...
web3.js Web3.js returns "Cannot find module 'web3-requestManager'"
The same thing after npm update web3 updates to web3@1.0.0-beta2 instead of current web3@1.0.0-beta3...
metamask extension Allow dapp to disconnect accounts
Great success! Pasting code here for others. What problem are you trying to solve? With the new upda...
ccxt Bitfinex margin trading
Hi! Bitfinex has several types of accounts including an exchange account and a margin account ...
go ethereum why my chaindata size up to 400GB?
@MysticRyuujin We're working on a memory cache to reduce database writes quite significantly (PoC te...
truffle 3.3.0 Update "fsevents is not a constructor" when running truffle serve
From #448: Workaround would be to run npm run dev instead of truffle serve Works for me on macOS 10....
web3.js TypeError: token.methods.balanceOf(...).call(...).on is not a function
For now you can use - Hi I am trying to get ERC20 tokens balance on some address with web3.js lib bu...
solidity Proposal: use and recommend .solidity file extension (for syntax highlighting on github)
They're visionaries God bless their .sols EDIT: I am absolutely killin' it tonight. ...
truffle Truffle compiler option 'contracts_build_directory' inconsistent behavior
I got problem at return binding.readdir(pathModule.toNamespacedPath(path) options.encoding) instead ...
web3 react New Version: v6!
we did it!! yarn add @web3-react/*@latest (6.0.2) Hi web3-react peeps! I want to give everyone a sta...
ethers.js How to pass unsafe numbers into BigNumber?
Well keep in mind an unsafe number is already unsafe Passing it into a BigNumber won't save you beca...
web3.js getTransactionCount() returns incorrect nonce when transactions are pending
I believe you can call web3.eth.getTransactionCount(address 'pending') to include pending transactio...
web3.js Bignumber issue in web3 invalid number value (arg="_value", coderType="uint256", value=10000000000000000)
Heads up 2021 still remains a issue. Getting invalid number error when calling a method of a contrac...
metamask extension etimateGas failing 9/10 times when it should succeed
To understand this problem it's important to understand the difference between gasPrice and gasLimit...
go ethereum Random ordering of equally-priced transactions incentivises competitive spam
If Geth does move away from randomized choice I would prefer FIFO instead of lowest tx hash ...
web3.js Cannot find name 'Buffer'. Can't find module 'net'.
ahhh i think i found your issue Expected behavior Ionic/Angular handles the Web3 import fine and ser...
brownie ValueError: Unable to expand environment variable in host setting
I also ran into this issue running brownie test -k test_get_entrance_fee --network rinkeby solved by...
go ethereum Error starting protocol stack: missing block number for head header hash
@karalabe Having same problem starting from yesterday System information Geth version: 1.6.0 OS & Ve...
ethers.js Error: gas required exceeds allowance or always failing transaction
This seems to be an issue with certain contracts with certain backends where the backend fails to co...
truffle Testing contracts raising exceptions in Truffle
Actually I found a solution to this problem to write cleaner tests In a helper.js file under test/ f...
mist Ethereum wallet will not sync past the last 65 blocks
Syncing Ethereum is a pain point for many people so I'll try to detail what's happening behind the s...