-
Notifications
You must be signed in to change notification settings - Fork 29
Estimate gas for all contract deployments and transactions #211
Conversation
@@ -42,15 +43,15 @@ export default class ReleaseDeployer { | |||
async _deployLocalContract(contractName) { | |||
const contractClass = Contracts.getFromLib(contractName) | |||
log.info(`Deploying new ${contractName}...`) | |||
const implementation = await contractClass.new() | |||
const implementation = await deploy(contractClass, [], this.txParams) |
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.
Note that txParams
was missing here
Add new Deploy function to deploy contracts running an estimateGas call before to send the precise amount of gas needed. All classes now use this function to deploy both user and library contracts.
d09b0f7
to
2ac1fa7
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.
Looks good!
We should be using all lowercase for deploy
, since it's a function. So the new file should be utils/deploy.js
, and the export in index.js
should be deploy
.
Should we leave a comment somewhere saying that this is a temporary patch for something that should be handled by the underlying Contract class?
src/utils/Deploy.js
Outdated
|
||
// Get raw binary transaction for creating the contract | ||
const txOpts = { data: contract.binary, ... txParams }; | ||
const txData = web3.eth.contract(contract.abi).new.getData(...args, txOpts); |
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 you can get the underlying web3.js Contract
instance through contract.contract
. (See here.)
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.
For some reason it's failing, so I'll keep using this way of setting up the web3 contract
test/src/utils/Deploy.test.js
Outdated
}); | ||
}); | ||
|
||
describe('with a constructor', 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 is the behavior when the constructor reverts? We should probably add tests for this scenario too.
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.
Looking good to me! I'd use the new deploy function in our tests too
src/utils/Deploy.js
Outdated
return contract.new(...args, { gas: estimatedGas, ... txParams }); | ||
} | ||
|
||
export default deploy; |
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.
nitpick: you can export the function from the first line with export default async function ...
src/utils/Deploy.js
Outdated
else resolve(gas); | ||
} | ||
); | ||
}); |
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.
should we add an estimation of the gas price in case no one was given?
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'd rather have the function fail actually
@facuspagnuolo @frangio I've added a new commit addressing your comments, and also with a new |
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.
Do we have any idea as to the performance cost of estimating all transactions before sending them?
I'm not sure why the file with the helpers is called Transactions.js
! Maybe it would be better to call it gasEstimation.js
.
@@ -26,29 +27,29 @@ export default class Release { | |||
} | |||
|
|||
async owner() { | |||
return await this._release.owner(this.txParams) |
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.
Does removing this.txParams
here have anything to do with gas estimation? Otherwise, why remove it?
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 preferred to remove the txParams
, which have information for transactions (such as sender), from all the static calls. They should not make any difference at all.
}); | ||
|
||
it('handles failing constructors', async function () { | ||
await assertRevert(deploy(this.WithConstructorImplementation, [0, "foo"])); |
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.
My previous question rather was about how estimateGas
behaves if the underlying transaction reverts. I suppose it estimates how much gas is needed to hit the revert
?
I have a feeling that I've seen some tools (MyCrypto?) warn me before sending a transaction that is guaranteed to revert, and gas estimation sounds like the moment when they can figure that out. Maybe we should just open another issue to consider implementing such warnings. WDYT?
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.
Actually estimateGas
returns an error if the transaction fails. On geth I'm getting a Error: gas required exceeds allowance or always failing transaction
. This means that we will never send the tx, but actually fail beforehand. So this optimization is already in place :-)
That will depend almost exclusively on the available resources of the node executing the
I wanted to use a name generic enough so that any further improvements we make to the sendTx and deploy methods can be placed here. Eventually, if we swap out truffle, I'd expect to handle the calls to the new fwk in this class directly. But I agree that it is not representative of what the functions in this file do. I can change it if you think it's better for now. |
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 really like we found a solution for this issue, but I'd prefer to have these functions (deploy and sendTx) already in our wrapped contracts so any users don't have to learn a new way of deploying or calling a contract. This came up to my mind after all the modifications we needed to do to our code to use it. Which means, everyone using zos-lib that wants to have this improvement will need to do the same. What do you think guys?
changelog.md
Outdated
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. | |||
|
|||
## [Unreleased] | |||
|
|||
### Changed | |||
- Contract deployments are executed with an estimate of the gas needed, instead of using the network default |
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.
Add the sendTransaction
function if we decide to keep it as is, actually we can add both functions in the "Added" section since they are being exported
I disagree there. As much as I love the code I wrote myself and would like to see everyone else using it, I don't like forcing a feature down a user's throat. The helpers are available if a user wants to use them, but are not in the way or mandatory. Just think how much we have complained when we stumble upon something we cannot change on the toolchain (whether it is truffle or web3). This is the typical framework vs library dichotomy: whether you want something to already provide you with all sensible defaults for you to work, or you have to manually opt-in into every feature you want to pick. Point is, when the framework has a bug or something you actually don't want, it's a real PITA. Anyway, I'll cut the rambling here. I'd prefer merging this as-is, and then revisit this once we start seriously reviewing the entire toolchain. |
a15130c
to
50fe666
Compare
I see your point, I'm actually kind of in favor of what you are saying, maybe I didn't make myself clear. With "in our wrapped contracts" I meant having those functions integrated with the My idea was just to see how this new functionality would fit being integrated with our I do agree with merging it as is for now, we can keep improving it later |
Got it. Although I'm still not 100% convinced, I understand that it makes sense that if you request a contact via zos-lib, that contract has all the goodies that zos-lib has to offer. I'll open a new issue for that. |
…s/zos-lib#211) * Deployer function for estimating gas upon deploy * Estimate gas in all transactions via sendTransaction method
Add new deploy function to deploy contracts running an estimateGas
call before to send the precise amount of gas needed. All classes
now use this function to deploy both user and library contracts.
Add new sendTransaction function to estimate gas on a transaction
to a contract as well.
Fixes zeppelinos/zos-cli#312
Fixes #212