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

RFQ-T Firm Quotes #162

Merged
merged 37 commits into from
Apr 16, 2020
Merged

RFQ-T Firm Quotes #162

merged 37 commits into from
Apr 16, 2020

Conversation

feuGeneA
Copy link
Contributor

@feuGeneA feuGeneA commented Apr 7, 2020

These changes depend on the changes in 0xProject/0x-monorepo#2541 .

Every commit is crafted to be completely independent and atomic. I suggest you review them one at a time, in order to give better context, rather than just reviewing all of the changes at once.

The following commits should be removed before merging:

  • TEMPORARY: Update gitpkg monorepo references, 26d8527
    • these will likely change once the monorepo PR is merged
  • TEMPORARY: use gene's ganache snapshot for tests, 0b09bab
    • this will go away once the monorepo PR is merged and the ganache snapshot is deployed from it.

Checklist:

  • MORE TESTS
  • Create new "should validate?" boolean for firm quotes which is true or false, defaulting to true. Tell integrators to explicitly send in false if their taker address is a smart contract.

They're already deployed in the snapshot.  No need to deploy them
again.
To avoid trying to descend into docker-created folders, which are
root-access-only when running in a Linux environment.
Because it's used (in the mocha invocation) and wasn't present after
`yarn install`.
package.json Outdated Show resolved Hide resolved
src/config.ts Outdated Show resolved Hide resolved
src/types.ts Outdated Show resolved Hide resolved
package.json Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
@feuGeneA
Copy link
Contributor Author

feuGeneA commented Apr 8, 2020

@steveklebanoff , @PirosB3 and I had a call where we went over this code together. Aside from the inline comments I've already made, we also generated this feedback:

  • Should we have whitelists in BOTH the 0x API AND in RFQ-T providers themselves?

  • We should emit some log entries (a) just before hitting RFQ-T quote providers, and (b) just after hitting them, so we can tell how long that process is taking in the wild.

  • How is axios pooling HTTP requests? Is it re-using sockets or reinstantiating them? Utilizing an HTTP keep-alive would be ideal.

  • With the code as written now, an RFQ-T taker MUST hold some amount of the taker asset.

    • This is because SwapService.calculateSwapQuoteAsync() says if (from) { ... this._estimateGasOrThrowRevertErrorAsync(...). Since an RFQ-T order always includes a taker address, it's falling into this bucket, and the fill simulation fails if the taker doesn't have any taker assets.

    • The holding of taker assets is a problem for CFL integrators like 1inch, where the taker is a smart contract and therefore would not be holding any tokens.

    • The only immediately available hacky fix would be to change it to say if (from && !intentOnFilling) { ... }. Ideally it would be if (from && !isRFQT) { ... }, but there's no notion of "isRFQT" in the code as written; intentOnFilling is the best we've got in this context.

    • That hacky fix is tenable if and only if we are comfortable excluding the gas estimation logic for RFQ-T orders.

    • We need to have TWO test cases, one that has taker holding assets, one that doesn't.

src/config.ts Outdated Show resolved Hide resolved
src/services/swap_service.ts Outdated Show resolved Hide resolved
} = params;
const assetSwapperOpts = {
...ASSET_SWAPPER_MARKET_ORDERS_OPTS,
slippagePercentage,
bridgeSlippage: slippagePercentage,
gasPrice: providedGasPrice,
excludedSources, // TODO(dave4506): overrides the excluded sources selected by chainId
apiKey,
intentOnFilling,
takerAddress: from,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider not conflating from and takerAddress. As you discovered, this is sometimes not often the case. I.e Via forwarder takerAddress is the Forwarder, from is the end user.

What happens when the Forwarder is used? the takerAddress in the order MUST be the Forwarder contract.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to account for this here: 0255b25. Does that address the issue?

src/types.ts Outdated Show resolved Hide resolved
src/config.ts Outdated Show resolved Hide resolved
feuGeneA added a commit that referenced this pull request Apr 9, 2020
feuGeneA added a commit that referenced this pull request Apr 9, 2020
Just pass the API key through to the maker.

Addresses review comment #162 (comment)
feuGeneA added a commit that referenced this pull request Apr 9, 2020
feuGeneA added a commit that referenced this pull request Apr 9, 2020
feuGeneA added a commit that referenced this pull request Apr 10, 2020
feuGeneA added a commit that referenced this pull request Apr 10, 2020
Just pass the API key through to the maker.

Addresses review comment #162 (comment)
feuGeneA added a commit that referenced this pull request Apr 10, 2020
feuGeneA added a commit that referenced this pull request Apr 10, 2020
feuGeneA added a commit that referenced this pull request Apr 10, 2020
feuGeneA added a commit that referenced this pull request Apr 10, 2020
src/config.ts Outdated Show resolved Hide resolved
src/config.ts Outdated Show resolved Hide resolved
req.query.intentOnFilling === undefined
? undefined
: {
intentOnFilling: ['true', ''].includes(req.query.intentOnFilling) ? true : false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just do something like the following?

const rfqt = req.query.intentOnFilling === 'true'  ? { intentOnFilling: true } : undefined;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some digging when I updated the schemas here. I had initially wanted to make them type: "boolean" (whatever exactly that would mean!) but the jsonschema package didn't handle that nicely. Later discovered this question which is a good analog to what we're doing here: OAI/OpenAPI-Specification#1782

I changed this here because I liked the idea of the mere presence of this flag indicating it should be true, eg /quote?intentOnFilling&....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How we resolve #162 (comment) will impact this

};
// tslint:disable-next-line:boolean-naming
const skipValidation =
req.query.skipValidation === undefined ? false : ['true', ''].includes(req.query.skipValidation) ? true : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to consider req.query.skipValidation === '' as true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same logic behind my recent change to intentOnFilling. I think it makes logical sense to be able to say just /quote?skipValidation&..., and when that's the query string, req.query here contains "skipValidation": "".

"type": "string"
},
"intentOnFilling": {
"type": "string",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to. I tried. jsonschema choked on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At test runtime i get this json schema error

{\"field\":\"instance.intentOnFilling\",\"code\":1001,\"reason\":\"is not of a type(s) boolean\"}

This happened no matter whether my client said quote?intentOnFilling or quote?intenOnFilling=true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

I think this schema could be cleaner if we:

This would allow ?skipValidation=truue to raise a schema error instead of silently being set to false on our backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How's this: bb2814a

feuGeneA added a commit that referenced this pull request Apr 15, 2020
? undefined
: {
...rfqt,
takerAddress: isETHSell ? getContractAddressesForChainOrThrow(CHAIN_ID).forwarder : from,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add a comment describing what's happening here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 03f7673

@@ -120,7 +140,7 @@ export class SwapService {
const affiliatedData = this._attributeCallData(data, affiliateAddress);

let suggestedGasEstimate = new BigNumber(gas);
if (from) {
if (!skipValidation && from) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@steveklebanoff
Copy link
Contributor

LGTM pending:

* generate source maps

* abstract tests out into nested contexts

* test for skipping validation

* dont include order for maker who does not have allowances set

* bad api key test

* fix test names and explicitly deposit so taker can fill
feuGeneA added a commit that referenced this pull request Apr 16, 2020
feuGeneA added a commit that referenced this pull request Apr 16, 2020
Pin to a gitpkg publish of the monorepo dependencies changed to support
this PR to a commit hash of the development branch, rather than that of
my PR branch.
I published a custom ganache image, with a monorepo commit hash appended
to the version number for reference.
@feuGeneA
Copy link
Contributor Author

deploy kovan-staging

Copy link
Contributor

@steveklebanoff steveklebanoff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

const rfqt =
req.query.intentOnFilling === undefined
? undefined
: { intentOnFilling: req.query.intentOnFilling === 'true' ? true : false };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit but can't this just be { intentOnFilling: req.query.intentOnFilling === 'true' }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 735fe3e

},
"skipValidation": {
"type": "string",
"allowEmptyValue": true
"enum": ["true", "false"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@feuGeneA feuGeneA marked this pull request as ready for review April 16, 2020 20:32
@feuGeneA feuGeneA merged commit b6d40dc into master Apr 16, 2020
@feuGeneA feuGeneA deleted the rfqt branch April 16, 2020 21:12
@github-actions
Copy link

🎉 This PR is included in version 1.0.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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