Compare commits

...

29 Commits

Author SHA1 Message Date
Github Actions
c03a014740 Publish
- @0x/contracts-asset-proxy@3.7.10
 - @0x/contracts-broker@1.1.28
 - @0x/contracts-coordinator@3.1.29
 - @0x/contracts-dev-utils@1.3.27
 - @0x/contracts-erc1155@2.1.28
 - @0x/contracts-erc20@3.3.7
 - @0x/contracts-erc721@3.1.28
 - @0x/contracts-exchange-forwarder@4.2.29
 - @0x/contracts-exchange-libs@4.3.28
 - @0x/contracts-exchange@3.2.29
 - @0x/contracts-extensions@6.2.23
 - @0x/contracts-integrations@2.7.37
 - @0x/contracts-multisig@4.1.29
 - @0x/contracts-staking@2.0.36
 - @0x/contracts-test-utils@5.3.25
 - @0x/contracts-treasury@1.1.4
 - @0x/contracts-utils@4.7.7
 - @0x/contracts-zero-ex@0.22.1
 - @0x/asset-swapper@6.8.0
 - @0x/contract-artifacts@3.14.1
 - @0x/contract-wrappers-test@12.2.42
 - @0x/contract-wrappers@13.16.0
 - @0x/migrations@8.0.3
 - @0x/order-utils@10.4.20
 - @0x/protocol-utils@1.5.1
2021-04-28 07:48:31 +00:00
Github Actions
84e6d788aa Updated CHANGELOGS & MD docs 2021-04-28 07:48:27 +00:00
Jacob Evans
cd296b8767 feat: Prune Paths + Fast ABI (#183)
* Cull paths which cannot improve price

* fixes and rename

* optimizations

* disable ABI optimization for sampler

* fix lint

* use fastabi

* Update to fastabi 0.0.2

* update packages

* Fix NaN case

* update to published packages

* rebased

* Update generated wrappers
2021-04-28 17:16:24 +10:00
Lawrence Forman
5946d32a7d Berlin wrappers (#212)
* `@0x/contract-wrappers`: Regenerate wrappers using updated abi-gen
Update tools deps

* update deps to hopefully fix doc gen
2021-04-27 12:16:08 -04:00
Alex Kroeger
842dd8572b bump NativeOrdersFeature version to 1.2 (#213)
* bump version to 1.2

* update changelog
2021-04-27 08:11:13 -07:00
Github Actions
33e260f9db Publish
- @0x/contracts-integrations@2.7.36
 - @0x/contracts-treasury@1.1.3
 - @0x/contracts-zero-ex@0.22.0
 - @0x/asset-swapper@6.7.0
 - @0x/contract-wrappers-test@12.2.41
 - @0x/migrations@8.0.2
 - @0x/protocol-utils@1.5.0
2021-04-26 23:59:58 +00:00
Github Actions
c44f8d0060 Updated CHANGELOGS & MD docs 2021-04-26 23:59:53 +00:00
Kim Persson
411548a33e feat: PancakeSwap 2 integration [TKR-83] (#211)
* feat: PancakeSwap 2 integration

* chore: add PancakeSwap V2 changelog entry

Co-authored-by: Romain Butteaud <romain@0xproject.com>
2021-04-26 15:51:04 -07:00
Alex Kroeger
9a17ce1383 add registerAllowedSigner to NativeOrdersFeature (#195)
* add registerAllowedSigner to NativeOrdersFeature

* fix PR reference in changelog

* prettier

* add cancel pair orders functions for signers

* refactored cancelPairOrders logic, changed naming of signerRegistry to orderSigner registry everywhere, cleaned up tests

* updated changelog for protocol-utils, made batchCancelPairOrders functions more efficient

* clean up function documentation

* added additional tests for batchCancelPairsWithSigner functions, added additional checks for events being emitted correctly

* fix typos in function documentation

* fix typo in function documentation

* update docs

* update comments on cancel functions, small tweaks to docs
2021-04-26 14:32:35 -07:00
Romain Butteaud
2b120d0669 fix: feeType=positive_slippage logic [TKR-81] (#209)
* fix: Fix feeType=positive_slippage logic to not force the EP route

* fix: yarn prettier
2021-04-26 11:26:57 -07:00
Github Actions
6d877d5242 Publish
- @0x/contracts-integrations@2.7.35
 - @0x/asset-swapper@6.6.0
2021-04-16 17:07:22 +00:00
Github Actions
e4abd690e7 Updated CHANGELOGS & MD docs 2021-04-16 17:07:17 +00:00
Jacob Evans
2a194384b6 [asset-swapper] Support Ropsten testnet (#203) 2021-04-16 13:55:35 +10:00
Jacob Evans
1e069e6f8a Remove 10 days from protocol fees docs (#202) 2021-04-16 10:51:41 +10:00
Daniel Pyrathon
a019bb913d only set Last Look parameter if it's explicitly set (#200)
* only set Last Look parameter if it's explicitly set

* remove expoectation of having isLastLook
2021-04-14 16:38:55 -07:00
Github Actions
9ce73931f7 Publish
- @0x/contracts-integrations@2.7.34
 - @0x/asset-swapper@6.5.3
2021-04-14 20:56:21 +00:00
Github Actions
97020df178 Updated CHANGELOGS & MD docs 2021-04-14 20:56:14 +00:00
Lawrence Forman
dfb7b3de8f Apply slippage to non-native orders [TKR-39] (#198)
* `@0x/asset-swapper`: Apply slippage to FQT bridge orders

* review comments

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2021-04-13 19:24:50 -04:00
Github Actions
9e152912fe Publish
- @0x/contracts-integrations@2.7.33
 - @0x/asset-swapper@6.5.2
2021-04-13 11:51:04 +00:00
Github Actions
b2c2f1e1aa Updated CHANGELOGS & MD docs 2021-04-13 11:50:57 +00:00
Jacob Evans
629c7d8e92 Fix asset-swapper test (#199) 2021-04-13 21:01:26 +10:00
Jacob Evans
62f24d4356 [asset-swapper] add Native fee token on all chains (#191) 2021-04-13 08:21:26 +10:00
Github Actions
ae281c33ca Publish
- @0x/contracts-integrations@2.7.32
 - @0x/contracts-treasury@1.1.2
 - @0x/contracts-zero-ex@0.21.1
 - @0x/asset-swapper@6.5.1
 - @0x/contract-wrappers-test@12.2.40
 - @0x/migrations@8.0.1
 - @0x/protocol-utils@1.4.1
2021-04-12 20:37:59 +00:00
Github Actions
5d034dd106 Updated CHANGELOGS & MD docs 2021-04-12 20:37:55 +00:00
Romain Butteaud
c1f8df0eca chore: Component.finance, Smoothy.finance, Saddle.finance, Curve open pools, Gas schedule [TKR-1] (#182)
* chore: Component.finance, Smoothy.finance (mainnet + BSC), Saddle.finance, Curve open pools, adjusting gas schedule, fixing Shell buys

* chore: adding a Sampler for Smoothy.finance to only use whats in the contracts reserve

* fix: Smoothy sampler, only use approx. for buys, removing y and BUSD curve pools

* add CHANGELOGs

* fix: prettier

* add: FRAX Curve open pool

* fix: prettier

* chore: adjusting gas schedule for BSC Smoothy
2021-04-08 18:07:12 -07:00
Github Actions
76dda9eeda Publish
- @0x/contracts-integrations@2.7.31
 - @0x/asset-swapper@6.5.0
2021-04-08 20:27:04 +00:00
Github Actions
a9b84a92ac Updated CHANGELOGS & MD docs 2021-04-08 20:26:57 +00:00
mzhu25
0f7e881899 Add default liquidity provider registry and allow gas costs to be a function of tokens (#196) 2021-04-08 11:09:32 -07:00
mzhu25
6045f777ab Add Kyber DMM as a liquidity source (#194)
* Add Kyber DMM as a liquidity source

* update changelog
2021-04-07 10:08:19 -07:00
147 changed files with 5683 additions and 1462 deletions

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "3.7.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "3.7.9",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.7.10 - _April 28, 2021_
* Dependencies updated
## v3.7.9 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-asset-proxy",
"version": "3.7.9",
"version": "3.7.10",
"engines": {
"node": ">=6.12"
},
@@ -51,15 +51,15 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contract-wrappers": "^13.15.0",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contract-wrappers": "^13.16.0",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/tslint-config": "^4.1.4",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -67,7 +67,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereumjs-util": "^5.1.1",
"ethereumjs-util": "^7.0.10",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@@ -79,17 +79,17 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-erc1155": "^2.1.27",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/order-utils": "^10.4.19",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"ethereum-types": "^3.4.0",
"@0x/base-contract": "^6.3.2",
"@0x/contracts-erc1155": "^2.1.28",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/order-utils": "^10.4.20",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"ethereum-types": "^3.5.0",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -168,7 +168,7 @@ describe('StaticCallProxy', () => {
it('should revert if the hash of the output is different than expected expected', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const expectedResultHash = ethUtil.bufferToHex(ethUtil.keccak256(trueAsBuffer));
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
@@ -199,7 +199,7 @@ describe('StaticCallProxy', () => {
it('should be successful if a function call with one static input returns the correct value', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const expectedResultHash = ethUtil.bufferToHex(ethUtil.keccak256(trueAsBuffer));
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
@@ -232,7 +232,7 @@ describe('StaticCallProxy', () => {
const offset = '0000000000000000000000000000000000000000000000000000000000000020';
const encodedExpectedResultWithOffset = `0x${offset}${abiEncoder.encode(expectedResults).slice(2)}`;
const expectedResultHash = ethUtil.bufferToHex(
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
ethUtil.keccak256(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "1.1.28",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "1.1.27",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.1.28 - _April 28, 2021_
* Dependencies updated
## v1.1.27 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-broker",
"version": "1.1.27",
"version": "1.1.28",
"engines": {
"node": ">=6.12"
},
@@ -51,20 +51,20 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -84,11 +84,11 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/order-utils": "^10.4.19",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0"
"@0x/base-contract": "^6.3.2",
"@0x/order-utils": "^10.4.20",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "3.1.29",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "3.1.28",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.29 - _April 28, 2021_
* Dependencies updated
## v3.1.28 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-coordinator",
"version": "3.1.28",
"version": "3.1.29",
"engines": {
"node": ">=6.12"
},
@@ -52,17 +52,17 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-gen": "^2.0.32",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-gen": "^2.0.37",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -82,17 +82,17 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/assert": "^3.0.21",
"@0x/base-contract": "^6.2.18",
"@0x/assert": "^3.0.26",
"@0x/base-contract": "^6.3.2",
"@0x/contract-addresses": "^6.0.0",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/json-schemas": "^5.4.1",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/json-schemas": "^6.1.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0",
"http-status-codes": "^1.3.2"
},
"publishConfig": {

View File

@@ -1,8 +1,4 @@
import { assert as sharedAssert } from '@0x/assert';
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
import { Schema } from '@0x/json-schemas'; // tslint:disable-line:no-unused-variable
import { Order } from '@0x/types'; // tslint:disable-line:no-unused-variable
import { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable
import { Web3Wrapper } from '@0x/web3-wrapper';
export const assert = {

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "1.3.27",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "1.3.26",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.3.27 - _April 28, 2021_
* Dependencies updated
## v1.3.26 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-dev-utils",
"version": "1.3.26",
"version": "1.3.27",
"engines": {
"node": ">=6.12"
},
@@ -41,18 +41,18 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/dev-utils",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/assert": "^3.0.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/assert": "^3.0.26",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0",
"ethers": "~4.0.4",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -63,7 +63,7 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/base-contract": "^6.3.2",
"@types/node": "12.12.54"
},
"publishConfig": {

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "2.1.28",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "2.1.27",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.1.28 - _April 28, 2021_
* Dependencies updated
## v2.1.27 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc1155",
"version": "2.1.27",
"version": "2.1.28",
"engines": {
"node": ">=6.12"
},
@@ -52,15 +52,15 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -68,7 +68,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.4.0",
"ethereum-types": "^3.5.0",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@@ -80,10 +80,10 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/base-contract": "^6.3.2",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "3.3.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "3.3.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.3.7 - _April 28, 2021_
* Dependencies updated
## v3.3.6 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20",
"version": "3.3.6",
"version": "3.3.7",
"engines": {
"node": ">=6.12"
},
@@ -51,18 +51,18 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -70,7 +70,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.4.0",
"ethereum-types": "^3.5.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -82,7 +82,7 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18"
"@0x/base-contract": "^6.3.2"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "3.1.28",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "3.1.27",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.28 - _April 28, 2021_
* Dependencies updated
## v3.1.27 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc721",
"version": "3.1.27",
"version": "3.1.28",
"engines": {
"node": ">=6.12"
},
@@ -52,18 +52,18 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -71,7 +71,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.4.0",
"ethereum-types": "^3.5.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -84,7 +84,7 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18"
"@0x/base-contract": "^6.3.2"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "4.2.29",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "4.2.28",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.2.29 - _April 28, 2021_
* Dependencies updated
## v4.2.28 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-forwarder",
"version": "4.2.28",
"version": "4.2.29",
"engines": {
"node": ">=6.12"
},
@@ -52,25 +52,25 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-erc1155": "^2.1.27",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-erc1155": "^2.1.28",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -90,9 +90,9 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/typescript-typings": "^5.1.6",
"ethereum-types": "^3.4.0"
"@0x/base-contract": "^6.3.2",
"@0x/typescript-typings": "^5.2.0",
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "4.3.28",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "4.3.27",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.3.28 - _April 28, 2021_
* Dependencies updated
## v4.3.27 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-libs",
"version": "4.3.27",
"version": "4.3.28",
"engines": {
"node": ">=6.12"
},
@@ -52,14 +52,14 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/libs",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-gen": "^2.0.32",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/subproviders": "^6.4.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-gen": "^2.0.37",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/subproviders": "^6.5.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -67,7 +67,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereumjs-util": "^5.1.1",
"ethereumjs-util": "^7.0.10",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -80,14 +80,14 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/order-utils": "^10.4.19",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0"
"@0x/base-contract": "^6.3.2",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/order-utils": "^10.4.20",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "3.2.29",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "3.2.28",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.2.29 - _April 28, 2021_
* Dependencies updated
## v3.2.28 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange",
"version": "3.2.28",
"version": "3.2.29",
"engines": {
"node": ">=6.12"
},
@@ -52,21 +52,21 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-multisig": "^4.1.28",
"@0x/contracts-staking": "^2.0.35",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-multisig": "^4.1.29",
"@0x/contracts-staking": "^2.0.36",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -74,8 +74,8 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10",
"js-combinatorics": "^0.5.3",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -88,13 +88,13 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-erc1155": "^2.1.27",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/order-utils": "^10.4.19",
"@0x/utils": "^6.2.0",
"@0x/base-contract": "^6.3.2",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-erc1155": "^2.1.28",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/order-utils": "^10.4.20",
"@0x/utils": "^6.4.2",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -86,7 +86,7 @@ blockchainTests.resets('MixinSignatureValidator', env => {
const SIGNATURE_LENGTH = 65;
const generateRandomSignature = (): string => hexUtils.random(SIGNATURE_LENGTH);
const hashBytes = (bytesHex: string): string => ethUtil.bufferToHex(ethUtil.sha3(ethUtil.toBuffer(bytesHex)));
const hashBytes = (bytesHex: string): string => hexUtils.hash(bytesHex);
const signDataHex = (dataHex: string, privateKey: Buffer): string => {
const ecSignature = ethUtil.ecsign(ethUtil.toBuffer(dataHex), privateKey);
return hexUtils.concat(ecSignature.v, ecSignature.r, ecSignature.s);

View File

@@ -12,7 +12,6 @@ import { ReferenceFunctions as UtilReferenceFunctions, SafeMathRevertErrors } fr
import { FillResults, Order } from '@0x/types';
import { AnyRevertError, BigNumber, ExchangeRevertErrors, hexUtils, StringRevertError } from '@0x/utils';
import { LogEntry, LogWithDecodedArgs } from 'ethereum-types';
import * as ethjs from 'ethereumjs-util';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
@@ -104,7 +103,7 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
// Creates a deterministic order signature, even though no signature validation
// actually occurs in the test contract.
function createOrderSignature(order: Order): string {
return ethjs.bufferToHex(ethjs.sha3(ethjs.toBuffer(orderHashUtils.getOrderHashHex(order))));
return hexUtils.hash(orderHashUtils.getOrderHashHex(order));
}
// Asserts that `_fillOrder()` was called in the same order and with the same

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "6.2.23",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "6.2.22",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v6.2.23 - _April 28, 2021_
* Dependencies updated
## v6.2.22 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-extensions",
"version": "6.2.22",
"version": "6.2.23",
"engines": {
"node": ">=6.12"
},
@@ -52,23 +52,23 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -77,7 +77,7 @@
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
"ethereumjs-util": "^7.0.10",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -90,10 +90,10 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/typescript-typings": "^5.1.6",
"ethereum-types": "^3.4.0"
"@0x/base-contract": "^6.3.2",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/typescript-typings": "^5.2.0",
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.7.30",
"version": "2.7.37",
"private": true,
"engines": {
"node": ">=6.12"
@@ -52,25 +52,25 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/abi-gen": "^5.5.2",
"@0x/contract-addresses": "^6.0.0",
"@0x/contract-wrappers": "^13.15.0",
"@0x/contracts-broker": "^1.1.27",
"@0x/contracts-coordinator": "^3.1.28",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-exchange-forwarder": "^4.2.28",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-extensions": "^6.2.22",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-utils": "^4.7.6",
"@0x/contract-wrappers": "^13.16.0",
"@0x/contracts-broker": "^1.1.28",
"@0x/contracts-coordinator": "^3.1.29",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-exchange-forwarder": "^4.2.29",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-extensions": "^6.2.23",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-utils": "^4.7.7",
"@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^4.2.1",
"@0x/migrations": "^8.0.0",
"@0x/order-utils": "^10.4.19",
"@0x/protocol-utils": "^1.4.0",
"@0x/sol-compiler": "^4.6.1",
"@0x/tslint-config": "^4.1.3",
"@0x/web3-wrapper": "^7.4.1",
"@0x/dev-utils": "^4.2.6",
"@0x/migrations": "^8.0.3",
"@0x/order-utils": "^10.4.20",
"@0x/protocol-utils": "^1.5.1",
"@0x/sol-compiler": "^4.7.2",
"@0x/tslint-config": "^4.1.4",
"@0x/web3-wrapper": "^7.5.2",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -93,23 +93,23 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/asset-swapper": "^6.4.0",
"@0x/base-contract": "^6.2.18",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-erc1155": "^2.1.27",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-erc721": "^3.1.27",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-multisig": "^4.1.28",
"@0x/contracts-staking": "^2.0.35",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-zero-ex": "^0.21.0",
"@0x/subproviders": "^6.4.1",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^6.2.0",
"@0x/asset-swapper": "^6.8.0",
"@0x/base-contract": "^6.3.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc1155": "^2.1.28",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-erc721": "^3.1.28",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-multisig": "^4.1.29",
"@0x/contracts-staking": "^2.0.36",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-zero-ex": "^0.22.1",
"@0x/subproviders": "^6.5.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "4.1.29",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "4.1.28",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.1.29 - _April 28, 2021_
* Dependencies updated
## v4.1.28 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-multisig",
"version": "4.1.28",
"version": "4.1.29",
"engines": {
"node": ">=6.12"
},
@@ -49,18 +49,18 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/multisig",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/sol-compiler": "^4.6.1",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/sol-compiler": "^4.7.2",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",
@@ -78,9 +78,9 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/typescript-typings": "^5.1.6",
"ethereum-types": "^3.4.0"
"@0x/base-contract": "^6.3.2",
"@0x/typescript-typings": "^5.2.0",
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "2.0.36",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "2.0.35",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.36 - _April 28, 2021_
* Dependencies updated
## v2.0.35 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-staking",
"version": "2.0.35",
"version": "2.0.36",
"engines": {
"node": ">=6.12"
},
@@ -53,20 +53,20 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-dev-utils": "^1.3.26",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-utils": "^4.7.6",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-dev-utils": "^1.3.27",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-utils": "^4.7.7",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/web3-wrapper": "^7.4.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/web3-wrapper": "^7.5.2",
"@types/lodash": "4.14.104",
"@types/node": "12.12.54",
"chai": "^4.0.1",
@@ -87,12 +87,12 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1"
"@0x/base-contract": "^6.3.2",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "5.3.25",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "5.3.24",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v5.3.25 - _April 28, 2021_
* Dependencies updated
## v5.3.24 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-test-utils",
"version": "5.3.24",
"version": "5.3.25",
"engines": {
"node": ">=6.12"
},
@@ -34,28 +34,28 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/test-utils",
"devDependencies": {
"@0x/sol-compiler": "^4.6.1",
"@0x/tslint-config": "^4.1.3",
"@0x/sol-compiler": "^4.7.2",
"@0x/tslint-config": "^4.1.4",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typescript": "4.2.2"
},
"dependencies": {
"@0x/assert": "^3.0.21",
"@0x/base-contract": "^6.2.18",
"@0x/assert": "^3.0.26",
"@0x/base-contract": "^6.3.2",
"@0x/contract-addresses": "^6.0.0",
"@0x/dev-utils": "^4.2.1",
"@0x/json-schemas": "^5.4.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-coverage": "^4.0.31",
"@0x/sol-profiler": "^4.1.21",
"@0x/sol-trace": "^3.0.31",
"@0x/subproviders": "^6.4.1",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/dev-utils": "^4.2.6",
"@0x/json-schemas": "^6.1.2",
"@0x/order-utils": "^10.4.20",
"@0x/sol-coverage": "^4.0.36",
"@0x/sol-profiler": "^4.1.26",
"@0x/sol-trace": "^3.0.36",
"@0x/subproviders": "^6.5.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@types/bn.js": "^4.11.0",
"@types/js-combinatorics": "^0.5.29",
"@types/lodash": "4.14.104",
@@ -67,8 +67,8 @@
"chai-bignumber": "^3.0.0",
"decimal.js": "^10.2.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10",
"ethers": "~4.0.4",
"js-combinatorics": "^0.5.3",
"lodash": "^4.17.11",

View File

@@ -77,7 +77,7 @@ export const constants = {
ZERO_AMOUNT: new BigNumber(0),
PERCENTAGE_DENOMINATOR: new BigNumber(10).pow(18),
TIME_BUFFER: new BigNumber(1000),
KECCAK256_NULL: ethUtil.addHexPrefix(ethUtil.bufferToHex(ethUtil.SHA3_NULL)),
KECCAK256_NULL: ethUtil.bufferToHex(ethUtil.keccak256(Buffer.alloc(0))),
MAX_UINT256_ROOT: new BigNumber('340282366920938463463374607431768211456'),
ONE_ETHER: new BigNumber(1e18),
EIP712_DOMAIN_NAME: '0x Protocol',

View File

@@ -57,9 +57,7 @@ describe('Order hashing', () => {
...order,
takerAddress: (null as any) as string,
};
const expectedErrorMessage = `Order taker must be of type string. If you want anyone to be able to fill an order - pass ${
constants.NULL_ADDRESS
}`;
const expectedErrorMessage = `Expected order to conform to schema`;
expect(() => orderHashUtils.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
});
});

View File

@@ -1,4 +1,31 @@
[
{
"timestamp": 1619596077,
"version": "1.1.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1619481586,
"version": "1.1.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1618259868,
"version": "1.1.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "1.1.1",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.1.4 - _April 28, 2021_
* Dependencies updated
## v1.1.3 - _April 26, 2021_
* Dependencies updated
## v1.1.2 - _April 12, 2021_
* Dependencies updated
## v1.1.1 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-treasury",
"version": "1.1.1",
"version": "1.1.4",
"engines": {
"node": ">=6.12"
},
@@ -46,16 +46,16 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/abi-gen": "^5.5.2",
"@0x/contract-addresses": "^6.0.0",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-staking": "^2.0.35",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/sol-compiler": "^4.6.1",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-staking": "^2.0.36",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/tslint-config": "^4.1.4",
"@types/isomorphic-fetch": "^0.0.35",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -72,15 +72,15 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/protocol-utils": "^1.4.0",
"@0x/subproviders": "^6.4.1",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1"
"@0x/base-contract": "^6.3.2",
"@0x/protocol-utils": "^1.5.1",
"@0x/subproviders": "^6.5.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1619596077,
"version": "4.7.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1617311315,
"version": "4.7.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.7.7 - _April 28, 2021_
* Dependencies updated
## v4.7.6 - _April 1, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-utils",
"version": "4.7.6",
"version": "4.7.7",
"engines": {
"node": ">=6.12"
},
@@ -50,15 +50,15 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/utils",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/web3-wrapper": "^7.4.1",
"@0x/abi-gen": "^5.5.2",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@0x/web3-wrapper": "^7.5.2",
"@types/bn.js": "^4.11.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -67,7 +67,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereumjs-util": "^5.1.1",
"ethereumjs-util": "^7.0.10",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -79,11 +79,11 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/base-contract": "^6.3.2",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"bn.js": "^4.11.8",
"ethereum-types": "^3.4.0"
"ethereum-types": "^3.5.0"
},
"publishConfig": {
"access": "public"

View File

@@ -2,7 +2,6 @@ import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/con
import { BlockchainLifecycle } from '@0x/dev-utils';
import { BigNumber, hexUtils, signTypedDataUtils } from '@0x/utils';
import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
@@ -78,7 +77,7 @@ describe('LibEIP712', () => {
// Hash the provided input to get the expected hash
const input = '0x1901'.concat(unprefixedDomainHash.concat(unprefixedHashStruct));
const expectedHash = '0x'.concat(ethUtil.sha3(input).toString('hex'));
const expectedHash = hexUtils.hash(input);
// Get the actual hash by calling the smart contract
const actualHash = await lib.externalHashEIP712Message(domainHash, hashStruct).callAsync();

View File

@@ -1,4 +1,33 @@
[
{
"version": "0.22.1",
"changes": [
{
"note": "bump feature version to 1.2",
"pr": 213
}
],
"timestamp": 1619596077
},
{
"version": "0.22.0",
"changes": [
{
"note": "Add order signer registry to NativeOrdersFeature",
"pr": 195
}
],
"timestamp": 1619481586
},
{
"timestamp": 1618259868,
"version": "0.21.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.21.0",
"changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.22.1 - _April 28, 2021_
* bump feature version to 1.2 (#213)
## v0.22.0 - _April 26, 2021_
* Add order signer registry to NativeOrdersFeature (#195)
## v0.21.1 - _April 12, 2021_
* Dependencies updated
## v0.21.0 - _April 1, 2021_
* Encoding protocol ID and source name in bridge source ID (#162)

View File

@@ -88,6 +88,21 @@ library LibNativeOrdersRichErrors {
);
}
function InvalidSignerError(
address maker,
address signer
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("InvalidSignerError(address,address)")),
maker,
signer
);
}
function OrderNotFillableBySenderError(
bytes32 orderHash,
address sender,

View File

@@ -34,7 +34,7 @@ contract NativeOrdersFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "LimitOrders";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 2, 0);
constructor(
address zeroExAddress,
@@ -74,9 +74,13 @@ contract NativeOrdersFeature is
_registerFeatureFunction(this.batchCancelLimitOrders.selector);
_registerFeatureFunction(this.batchCancelRfqOrders.selector);
_registerFeatureFunction(this.cancelPairLimitOrders.selector);
_registerFeatureFunction(this.cancelPairLimitOrdersWithSigner.selector);
_registerFeatureFunction(this.batchCancelPairLimitOrders.selector);
_registerFeatureFunction(this.batchCancelPairLimitOrdersWithSigner.selector);
_registerFeatureFunction(this.cancelPairRfqOrders.selector);
_registerFeatureFunction(this.cancelPairRfqOrdersWithSigner.selector);
_registerFeatureFunction(this.batchCancelPairRfqOrders.selector);
_registerFeatureFunction(this.batchCancelPairRfqOrdersWithSigner.selector);
_registerFeatureFunction(this.getLimitOrderInfo.selector);
_registerFeatureFunction(this.getRfqOrderInfo.selector);
_registerFeatureFunction(this.getLimitOrderHash.selector);
@@ -87,6 +91,8 @@ contract NativeOrdersFeature is
_registerFeatureFunction(this.getRfqOrderRelevantState.selector);
_registerFeatureFunction(this.batchGetLimitOrderRelevantStates.selector);
_registerFeatureFunction(this.batchGetRfqOrderRelevantStates.selector);
_registerFeatureFunction(this.registerAllowedOrderSigner.selector);
_registerFeatureFunction(this.isValidOrderSigner.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
}

View File

@@ -113,4 +113,14 @@ interface INativeOrdersEvents {
address[] addrs,
bool allowed
);
/// @dev Emitted when new order signers are registered
/// @param maker The maker address that is registering a designated signer.
/// @param signer The address that will sign on behalf of maker.
/// @param allowed Indicates whether the address should be allowed.
event OrderSignerRegistered(
address maker,
address signer,
bool allowed
);
}

View File

@@ -137,13 +137,13 @@ interface INativeOrdersFeature is
external
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
/// @dev Cancel a single limit order. The caller must be the maker.
/// @dev Cancel a single limit order. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param order The limit order.
function cancelLimitOrder(LibNativeOrder.LimitOrder calldata order)
external;
/// @dev Cancel a single RFQ order. The caller must be the maker.
/// @dev Cancel a single RFQ order. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param order The RFQ order.
function cancelRfqOrder(LibNativeOrder.RfqOrder calldata order)
@@ -156,13 +156,13 @@ interface INativeOrdersFeature is
function registerAllowedRfqOrigins(address[] memory origins, bool allowed)
external;
/// @dev Cancel multiple limit orders. The caller must be the maker.
/// @dev Cancel multiple limit orders. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param orders The limit orders.
function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] calldata orders)
external;
/// @dev Cancel multiple RFQ orders. The caller must be the maker.
/// @dev Cancel multiple RFQ orders. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param orders The RFQ orders.
function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] calldata orders)
@@ -183,7 +183,23 @@ interface INativeOrdersFeature is
external;
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided. The caller must be the maker. Subsequent
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
/// @dev Cancel all limit orders for a given maker and pairs with salts less
/// than the values provided. The caller must be the maker. Subsequent
/// calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param makerTokens The maker tokens.
@@ -196,6 +212,22 @@ interface INativeOrdersFeature is
)
external;
/// @dev Cancel all limit orders for a given maker and pairs with salts less
/// than the values provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided. The caller must be the maker. Subsequent
/// calls to this function with the same caller and pair require the
@@ -211,7 +243,23 @@ interface INativeOrdersFeature is
external;
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided. The caller must be the maker. Subsequent
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
/// @dev Cancel all RFQ orders for a given maker and pairs with salts less
/// than the values provided. The caller must be the maker. Subsequent
/// calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param makerTokens The maker tokens.
@@ -224,6 +272,22 @@ interface INativeOrdersFeature is
)
external;
/// @dev Cancel all RFQ orders for a given maker and pairs with salts less
/// than the values provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
/// @dev Get the order info for a limit order.
/// @param order The limit order.
/// @return orderInfo Info about the order.
@@ -345,4 +409,25 @@ interface INativeOrdersFeature is
uint128[] memory actualFillableTakerTokenAmounts,
bool[] memory isSignatureValids
);
/// @dev Register a signer who can sign on behalf of msg.sender
/// This allows one to sign on behalf of a contract that calls this function
/// @param signer The address from which you plan to generate signatures
/// @param allowed True to register, false to unregister.
function registerAllowedOrderSigner(
address signer,
bool allowed
)
external;
/// @dev checks if a given address is registered to sign on behalf of a maker address
/// @param maker The maker address encoded in an order (can be a contract)
/// @param signer The address that is providing a signature
function isValidOrderSigner(
address maker,
address signer
)
external
view
returns (bool isAllowed);
}

View File

@@ -48,14 +48,14 @@ abstract contract NativeOrdersCancellation is
// solhint-disable no-empty-blocks
}
/// @dev Cancel a single limit order. The caller must be the maker.
/// @dev Cancel a single limit order. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param order The limit order.
function cancelLimitOrder(LibNativeOrder.LimitOrder memory order)
public
{
bytes32 orderHash = getLimitOrderHash(order);
if (msg.sender != order.maker) {
if (msg.sender != order.maker && !isValidOrderSigner(order.maker, msg.sender)) {
LibNativeOrdersRichErrors.OnlyOrderMakerAllowed(
orderHash,
msg.sender,
@@ -65,14 +65,14 @@ abstract contract NativeOrdersCancellation is
_cancelOrderHash(orderHash, order.maker);
}
/// @dev Cancel a single RFQ order. The caller must be the maker.
/// @dev Cancel a single RFQ order. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param order The RFQ order.
function cancelRfqOrder(LibNativeOrder.RfqOrder memory order)
public
{
bytes32 orderHash = getRfqOrderHash(order);
if (msg.sender != order.maker) {
if (msg.sender != order.maker && !isValidOrderSigner(order.maker, msg.sender)) {
LibNativeOrdersRichErrors.OnlyOrderMakerAllowed(
orderHash,
msg.sender,
@@ -82,7 +82,7 @@ abstract contract NativeOrdersCancellation is
_cancelOrderHash(orderHash, order.maker);
}
/// @dev Cancel multiple limit orders. The caller must be the maker.
/// @dev Cancel multiple limit orders. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param orders The limit orders.
function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] memory orders)
@@ -93,7 +93,7 @@ abstract contract NativeOrdersCancellation is
}
}
/// @dev Cancel multiple RFQ orders. The caller must be the maker.
/// @dev Cancel multiple RFQ orders. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param orders The RFQ orders.
function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] memory orders)
@@ -118,33 +118,34 @@ abstract contract NativeOrdersCancellation is
)
public
{
LibNativeOrdersStorage.Storage storage stor =
LibNativeOrdersStorage.getStorage();
_cancelPairLimitOrders(msg.sender, makerToken, takerToken, minValidSalt);
}
uint256 oldMinValidSalt =
stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[msg.sender]
[address(makerToken)]
[address(takerToken)];
// New min salt must >= the old one.
if (oldMinValidSalt > minValidSalt) {
LibNativeOrdersRichErrors.
CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
.rrevert();
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param maker the maker for whom the msg.sender is the signer.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
public
{
// verify that the signer is authorized for the maker
if (!isValidOrderSigner(maker, msg.sender)) {
LibNativeOrdersRichErrors.InvalidSignerError(
maker,
msg.sender
).rrevert();
}
stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[msg.sender]
[address(makerToken)]
[address(takerToken)] = minValidSalt;
emit PairCancelledLimitOrders(
msg.sender,
address(makerToken),
address(takerToken),
minValidSalt
);
_cancelPairLimitOrders(maker, makerToken, takerToken, minValidSalt);
}
/// @dev Cancel all limit orders for a given maker and pair with a salt less
@@ -168,7 +169,47 @@ abstract contract NativeOrdersCancellation is
);
for (uint256 i = 0; i < makerTokens.length; ++i) {
cancelPairLimitOrders(
_cancelPairLimitOrders(
msg.sender,
makerTokens[i],
takerTokens[i],
minValidSalts[i]
);
}
}
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param maker the maker for whom the msg.sender is the signer.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
public
{
require(
makerTokens.length == takerTokens.length &&
makerTokens.length == minValidSalts.length,
"NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS"
);
if (!isValidOrderSigner(maker, msg.sender)) {
LibNativeOrdersRichErrors.InvalidSignerError(
maker,
msg.sender
).rrevert();
}
for (uint256 i = 0; i < makerTokens.length; ++i) {
_cancelPairLimitOrders(
maker,
makerTokens[i],
takerTokens[i],
minValidSalts[i]
@@ -190,33 +231,33 @@ abstract contract NativeOrdersCancellation is
)
public
{
LibNativeOrdersStorage.Storage storage stor =
LibNativeOrdersStorage.getStorage();
_cancelPairRfqOrders(msg.sender, makerToken, takerToken, minValidSalt);
}
uint256 oldMinValidSalt =
stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[msg.sender]
[address(makerToken)]
[address(takerToken)];
// New min salt must >= the old one.
if (oldMinValidSalt > minValidSalt) {
LibNativeOrdersRichErrors.
CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
.rrevert();
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param maker the maker for whom the msg.sender is the signer.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
public
{
if (!isValidOrderSigner(maker, msg.sender)) {
LibNativeOrdersRichErrors.InvalidSignerError(
maker,
msg.sender
).rrevert();
}
stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[msg.sender]
[address(makerToken)]
[address(takerToken)] = minValidSalt;
emit PairCancelledRfqOrders(
msg.sender,
address(makerToken),
address(takerToken),
minValidSalt
);
_cancelPairRfqOrders(maker, makerToken, takerToken, minValidSalt);
}
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
@@ -240,7 +281,47 @@ abstract contract NativeOrdersCancellation is
);
for (uint256 i = 0; i < makerTokens.length; ++i) {
cancelPairRfqOrders(
_cancelPairRfqOrders(
msg.sender,
makerTokens[i],
takerTokens[i],
minValidSalts[i]
);
}
}
/// @dev Cancel all RFQ orders for a given maker and pairs with salts less
/// than the values provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same caller and pair require the
/// new salt to be >= the old salt.
/// @param maker the maker for whom the msg.sender is the signer.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
public
{
require(
makerTokens.length == takerTokens.length &&
makerTokens.length == minValidSalts.length,
"NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS"
);
if (!isValidOrderSigner(maker, msg.sender)) {
LibNativeOrdersRichErrors.InvalidSignerError(
maker,
msg.sender
).rrevert();
}
for (uint256 i = 0; i < makerTokens.length; ++i) {
_cancelPairRfqOrders(
maker,
makerTokens[i],
takerTokens[i],
minValidSalts[i]
@@ -262,4 +343,90 @@ abstract contract NativeOrdersCancellation is
emit OrderCancelled(orderHash, maker);
}
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided.
/// @param maker The target maker address
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function _cancelPairRfqOrders(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
private
{
LibNativeOrdersStorage.Storage storage stor =
LibNativeOrdersStorage.getStorage();
uint256 oldMinValidSalt =
stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[maker]
[address(makerToken)]
[address(takerToken)];
// New min salt must >= the old one.
if (oldMinValidSalt > minValidSalt) {
LibNativeOrdersRichErrors.
CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
.rrevert();
}
stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[maker]
[address(makerToken)]
[address(takerToken)] = minValidSalt;
emit PairCancelledRfqOrders(
maker,
address(makerToken),
address(takerToken),
minValidSalt
);
}
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided.
/// @param maker The target maker address
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function _cancelPairLimitOrders(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
private
{
LibNativeOrdersStorage.Storage storage stor =
LibNativeOrdersStorage.getStorage();
uint256 oldMinValidSalt =
stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[maker]
[address(makerToken)]
[address(takerToken)];
// New min salt must >= the old one.
if (oldMinValidSalt > minValidSalt) {
LibNativeOrdersRichErrors.
CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
.rrevert();
}
stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
[maker]
[address(makerToken)]
[address(takerToken)] = minValidSalt;
emit PairCancelledLimitOrders(
maker,
address(makerToken),
address(takerToken),
minValidSalt
);
}
}

View File

@@ -168,8 +168,10 @@ abstract contract NativeOrdersInfo is
orderInfo: orderInfo
})
);
isSignatureValid = order.maker ==
LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
address signerOfHash = LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
isSignatureValid =
(order.maker == signerOfHash) ||
isValidOrderSigner(order.maker, signerOfHash);
}
/// @dev Get order info, fillable amount, and signature validity for an RFQ order.
@@ -202,8 +204,10 @@ abstract contract NativeOrdersInfo is
orderInfo: orderInfo
})
);
isSignatureValid = order.maker ==
LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
address signerOfHash = LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
isSignatureValid =
(order.maker == signerOfHash) ||
isValidOrderSigner(order.maker, signerOfHash);
}
/// @dev Batch version of `getLimitOrderRelevantState()`, without reverting.
@@ -389,4 +393,22 @@ abstract contract NativeOrdersInfo is
uint256(params.orderTakerAmount)
).safeDowncastToUint128();
}
/// @dev checks if a given address is registered to sign on behalf of a maker address
/// @param maker The maker address encoded in an order (can be a contract)
/// @param signer The address that is providing a signature
function isValidOrderSigner(
address maker,
address signer
)
public
view
returns (bool isValid)
{
// returns false if it the mapping doesn't exist
return LibNativeOrdersStorage.getStorage()
.orderSignerRegistry
[maker]
[signer];
}
}

View File

@@ -370,7 +370,7 @@ abstract contract NativeOrdersSettlement is
orderInfo.orderHash,
params.signature
);
if (signer != params.order.maker) {
if (signer != params.order.maker && !isValidOrderSigner(params.order.maker, signer)) {
LibNativeOrdersRichErrors.OrderNotSignedByMakerError(
orderInfo.orderHash,
signer,
@@ -478,7 +478,7 @@ abstract contract NativeOrdersSettlement is
// Signature must be valid for the order.
{
address signer = LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
if (signer != order.maker) {
if (signer != order.maker && !isValidOrderSigner(order.maker, signer)) {
LibNativeOrdersRichErrors.OrderNotSignedByMakerError(
orderInfo.orderHash,
signer,
@@ -565,4 +565,21 @@ abstract contract NativeOrdersSettlement is
makerTokenFilledAmount
);
}
/// @dev register a signer who can sign on behalf of msg.sender
/// @param signer The address from which you plan to generate signatures
/// @param allowed True to register, false to unregister.
function registerAllowedOrderSigner(
address signer,
bool allowed
)
external
{
LibNativeOrdersStorage.Storage storage stor =
LibNativeOrdersStorage.getStorage();
stor.orderSignerRegistry[msg.sender][signer] = allowed;
emit OrderSignerRegistered(msg.sender, signer, allowed);
}
}

View File

@@ -43,6 +43,9 @@ library LibNativeOrdersStorage {
// For a given order origin, which tx.origin addresses are allowed to
// fill the order.
mapping(address => mapping(address => bool)) originRegistry;
// For a given maker address, which addresses are allowed to
// sign on its behalf.
mapping(address => mapping(address => bool)) orderSignerRegistry;
}
/// @dev Get the storage bucket for this contract.

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/OwnableV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../src/IZeroEx.sol";
contract TestOrderSignerRegistryWithContractWallet is OwnableV06 {
IZeroEx immutable zeroex;
constructor(IZeroEx _zeroex) public {
zeroex = _zeroex;
}
function registerAllowedOrderSigner(
address signer,
bool allowed
)
external
onlyOwner
{
zeroex.registerAllowedOrderSigner(signer, allowed);
}
function approveERC20(
IERC20TokenV06 token,
address spender,
uint256 value
)
external
onlyOwner
{
token.approve(spender, value);
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-zero-ex",
"version": "0.21.0",
"version": "0.22.1",
"engines": {
"node": ">=6.12"
},
@@ -43,7 +43,7 @@
"config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
},
"repository": {
"type": "git",
@@ -55,16 +55,16 @@
},
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
"devDependencies": {
"@0x/abi-gen": "^5.4.21",
"@0x/abi-gen": "^5.5.2",
"@0x/contract-addresses": "^6.0.0",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/dev-utils": "^4.2.1",
"@0x/order-utils": "^10.4.19",
"@0x/sol-compiler": "^4.6.1",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/dev-utils": "^4.2.6",
"@0x/order-utils": "^10.4.20",
"@0x/sol-compiler": "^4.7.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/tslint-config": "^4.1.4",
"@types/isomorphic-fetch": "^0.0.35",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -82,15 +82,15 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/protocol-utils": "^1.4.0",
"@0x/subproviders": "^6.4.1",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1"
"@0x/base-contract": "^6.3.2",
"@0x/protocol-utils": "^1.5.1",
"@0x/subproviders": "^6.5.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10"
},
"publishConfig": {
"access": "public"

View File

@@ -20,6 +20,7 @@ export function rlpEncodeNonce(nonce: number): string {
return ethjs.bufferToHex(ethjs.toBuffer(nonce));
} else {
const rlpNonce = ethjs.toBuffer(nonce);
// tslint:disable-next-line: restrict-plus-operands
return hexUtils.concat(rlpNonce.length + 0x80, ethjs.bufferToHex(rlpNonce));
}
}

View File

@@ -127,6 +127,7 @@ import * as TestMintableERC20Token from '../test/generated-artifacts/TestMintabl
import * as TestMintTokenERC20Transformer from '../test/generated-artifacts/TestMintTokenERC20Transformer.json';
import * as TestMooniswap from '../test/generated-artifacts/TestMooniswap.json';
import * as TestNativeOrdersFeature from '../test/generated-artifacts/TestNativeOrdersFeature.json';
import * as TestOrderSignerRegistryWithContractWallet from '../test/generated-artifacts/TestOrderSignerRegistryWithContractWallet.json';
import * as TestPermissionlessTransformerDeployerSuicidal from '../test/generated-artifacts/TestPermissionlessTransformerDeployerSuicidal.json';
import * as TestPermissionlessTransformerDeployerTransformer from '../test/generated-artifacts/TestPermissionlessTransformerDeployerTransformer.json';
import * as TestRfqOriginRegistration from '../test/generated-artifacts/TestRfqOriginRegistration.json';
@@ -278,6 +279,7 @@ export const artifacts = {
TestMintableERC20Token: TestMintableERC20Token as ContractArtifact,
TestMooniswap: TestMooniswap as ContractArtifact,
TestNativeOrdersFeature: TestNativeOrdersFeature as ContractArtifact,
TestOrderSignerRegistryWithContractWallet: TestOrderSignerRegistryWithContractWallet as ContractArtifact,
TestPermissionlessTransformerDeployerSuicidal: TestPermissionlessTransformerDeployerSuicidal as ContractArtifact,
TestPermissionlessTransformerDeployerTransformer: TestPermissionlessTransformerDeployerTransformer as ContractArtifact,
TestRfqOriginRegistration: TestRfqOriginRegistration as ContractArtifact,

View File

@@ -7,7 +7,15 @@ import {
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { LimitOrder, LimitOrderFields, OrderStatus, RevertErrors, RfqOrder, RfqOrderFields } from '@0x/protocol-utils';
import {
LimitOrder,
LimitOrderFields,
OrderStatus,
RevertErrors,
RfqOrder,
RfqOrderFields,
SignatureType,
} from '@0x/protocol-utils';
import { AnyRevertError, BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@@ -25,7 +33,11 @@ import {
getRandomRfqOrder,
NativeOrdersTestEnvironment,
} from '../utils/orders';
import { TestMintableERC20TokenContract, TestRfqOriginRegistrationContract } from '../wrappers';
import {
TestMintableERC20TokenContract,
TestOrderSignerRegistryWithContractWalletContract,
TestRfqOriginRegistrationContract,
} from '../wrappers';
blockchainTests.resets('NativeOrdersFeature', env => {
const { NULL_ADDRESS, MAX_UINT256, NULL_BYTES32, ZERO_AMOUNT } = constants;
@@ -36,17 +48,28 @@ blockchainTests.resets('NativeOrdersFeature', env => {
let taker: string;
let notMaker: string;
let notTaker: string;
let contractWalletOwner: string;
let contractWalletSigner: string;
let zeroEx: IZeroExContract;
let verifyingContract: string;
let makerToken: TestMintableERC20TokenContract;
let takerToken: TestMintableERC20TokenContract;
let wethToken: TestMintableERC20TokenContract;
let testRfqOriginRegistration: TestRfqOriginRegistrationContract;
let contractWallet: TestOrderSignerRegistryWithContractWalletContract;
let testUtils: NativeOrdersTestEnvironment;
before(async () => {
let owner;
[owner, maker, taker, notMaker, notTaker] = await env.getAccountAddressesAsync();
[
owner,
maker,
taker,
notMaker,
notTaker,
contractWalletOwner,
contractWalletSigner,
] = await env.getAccountAddressesAsync();
[makerToken, takerToken, wethToken] = await Promise.all(
[...new Array(3)].map(async () =>
TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
@@ -82,6 +105,21 @@ blockchainTests.resets('NativeOrdersFeature', env => {
env.txDefaults,
artifacts,
);
// contract wallet for signer delegation
contractWallet = await TestOrderSignerRegistryWithContractWalletContract.deployFrom0xArtifactAsync(
artifacts.TestOrderSignerRegistryWithContractWallet,
env.provider,
{
from: contractWalletOwner,
},
artifacts,
zeroEx.address,
);
await contractWallet
.approveERC20(makerToken.address, zeroEx.address, MAX_UINT256)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
testUtils = new NativeOrdersTestEnvironment(
maker,
taker,
@@ -1569,4 +1607,432 @@ blockchainTests.resets('NativeOrdersFeature', env => {
}
});
});
describe('registerAllowedSigner()', () => {
it('fires appropriate events', async () => {
const receiptAllow = await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
verifyEventsFromLogs(
receiptAllow.logs,
[
{
maker: contractWallet.address,
signer: contractWalletSigner,
allowed: true,
},
],
IZeroExEvents.OrderSignerRegistered,
);
// then disallow signer
const receiptDisallow = await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, false)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
verifyEventsFromLogs(
receiptDisallow.logs,
[
{
maker: contractWallet.address,
signer: contractWalletSigner,
allowed: false,
},
],
IZeroExEvents.OrderSignerRegistered,
);
});
it('allows for fills on orders signed by a approved signer', async () => {
const order = getTestRfqOrder({ maker: contractWallet.address });
const sig = await order.getSignatureWithProviderAsync(
env.provider,
SignatureType.EthSign,
contractWalletSigner,
);
// covers taker
await testUtils.prepareBalancesForOrdersAsync([order]);
// need to provide contract wallet with a balance
await makerToken.mint(contractWallet.address, order.makerAmount).awaitTransactionSuccessAsync();
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
await zeroEx.fillRfqOrder(order, sig, order.takerAmount).awaitTransactionSuccessAsync({ from: taker });
const info = await zeroEx.getRfqOrderInfo(order).callAsync();
assertOrderInfoEquals(info, {
status: OrderStatus.Filled,
orderHash: order.getHash(),
takerTokenFilledAmount: order.takerAmount,
});
});
it('disallows fills if the signer is revoked', async () => {
const order = getTestRfqOrder({ maker: contractWallet.address });
const sig = await order.getSignatureWithProviderAsync(
env.provider,
SignatureType.EthSign,
contractWalletSigner,
);
// covers taker
await testUtils.prepareBalancesForOrdersAsync([order]);
// need to provide contract wallet with a balance
await makerToken.mint(contractWallet.address, order.makerAmount).awaitTransactionSuccessAsync();
// first allow signer
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
// then disallow signer
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, false)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
const tx = zeroEx.fillRfqOrder(order, sig, order.takerAmount).awaitTransactionSuccessAsync({ from: taker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.OrderNotSignedByMakerError(
order.getHash(),
contractWalletSigner,
order.maker,
),
);
});
it(`doesn't allow fills with an unapproved signer`, async () => {
const order = getTestRfqOrder({ maker: contractWallet.address });
const sig = await order.getSignatureWithProviderAsync(env.provider, SignatureType.EthSign, maker);
// covers taker
await testUtils.prepareBalancesForOrdersAsync([order]);
// need to provide contract wallet with a balance
await makerToken.mint(contractWallet.address, order.makerAmount).awaitTransactionSuccessAsync();
const tx = zeroEx.fillRfqOrder(order, sig, order.takerAmount).awaitTransactionSuccessAsync({ from: taker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.OrderNotSignedByMakerError(order.getHash(), maker, order.maker),
);
});
it(`allows an approved signer to cancel an RFQ order`, async () => {
const order = getTestRfqOrder({ maker: contractWallet.address });
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
const receipt = await zeroEx
.cancelRfqOrder(order)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[{ maker: contractWallet.address, orderHash: order.getHash() }],
IZeroExEvents.OrderCancelled,
);
const info = await zeroEx.getRfqOrderInfo(order).callAsync();
assertOrderInfoEquals(info, {
status: OrderStatus.Cancelled,
orderHash: order.getHash(),
takerTokenFilledAmount: new BigNumber(0),
});
});
it(`allows an approved signer to cancel a limit order`, async () => {
const order = getTestLimitOrder({ maker: contractWallet.address });
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
const receipt = await zeroEx
.cancelLimitOrder(order)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[{ maker: contractWallet.address, orderHash: order.getHash() }],
IZeroExEvents.OrderCancelled,
);
const info = await zeroEx.getLimitOrderInfo(order).callAsync();
assertOrderInfoEquals(info, {
status: OrderStatus.Cancelled,
orderHash: order.getHash(),
takerTokenFilledAmount: new BigNumber(0),
});
});
it(`doesn't allow an unapproved signer to cancel an RFQ order`, async () => {
const order = getTestRfqOrder({ maker: contractWallet.address });
const tx = zeroEx.cancelRfqOrder(order).awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.OnlyOrderMakerAllowed(order.getHash(), maker, order.maker),
);
});
it(`doesn't allow an unapproved signer to cancel a limit order`, async () => {
const order = getTestLimitOrder({ maker: contractWallet.address });
const tx = zeroEx.cancelLimitOrder(order).awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.OnlyOrderMakerAllowed(order.getHash(), maker, order.maker),
);
});
it(`allows a signer to cancel pair RFQ orders`, async () => {
const order = getTestRfqOrder({ maker: contractWallet.address, salt: new BigNumber(1) });
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
// Cancel salts <= the order's
const minValidSalt = order.salt.plus(1);
const receipt = await zeroEx
.cancelPairRfqOrdersWithSigner(
contractWallet.address,
makerToken.address,
takerToken.address,
minValidSalt,
)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[
{
maker: contractWallet.address,
makerToken: makerToken.address,
takerToken: takerToken.address,
minValidSalt,
},
],
IZeroExEvents.PairCancelledRfqOrders,
);
const info = await zeroEx.getRfqOrderInfo(order).callAsync();
assertOrderInfoEquals(info, {
status: OrderStatus.Cancelled,
orderHash: order.getHash(),
takerTokenFilledAmount: new BigNumber(0),
});
});
it(`doesn't allow an unapproved signer to cancel pair RFQ orders`, async () => {
const minValidSalt = new BigNumber(2);
const tx = zeroEx
.cancelPairRfqOrdersWithSigner(
contractWallet.address,
makerToken.address,
takerToken.address,
minValidSalt,
)
.awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.InvalidSignerError(contractWallet.address, maker),
);
});
it(`allows a signer to cancel pair limit orders`, async () => {
const order = getTestLimitOrder({ maker: contractWallet.address, salt: new BigNumber(1) });
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
// Cancel salts <= the order's
const minValidSalt = order.salt.plus(1);
const receipt = await zeroEx
.cancelPairLimitOrdersWithSigner(
contractWallet.address,
makerToken.address,
takerToken.address,
minValidSalt,
)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[
{
maker: contractWallet.address,
makerToken: makerToken.address,
takerToken: takerToken.address,
minValidSalt,
},
],
IZeroExEvents.PairCancelledLimitOrders,
);
const info = await zeroEx.getLimitOrderInfo(order).callAsync();
assertOrderInfoEquals(info, {
status: OrderStatus.Cancelled,
orderHash: order.getHash(),
takerTokenFilledAmount: new BigNumber(0),
});
});
it(`doesn't allow an unapproved signer to cancel pair limit orders`, async () => {
const minValidSalt = new BigNumber(2);
const tx = zeroEx
.cancelPairLimitOrdersWithSigner(
contractWallet.address,
makerToken.address,
takerToken.address,
minValidSalt,
)
.awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.InvalidSignerError(contractWallet.address, maker),
);
});
it(`allows a signer to cancel multiple RFQ order pairs`, async () => {
const orders = [
getTestRfqOrder({ maker: contractWallet.address, salt: new BigNumber(1) }),
// Flip the tokens for the other order.
getTestRfqOrder({
makerToken: takerToken.address,
takerToken: makerToken.address,
maker: contractWallet.address,
salt: new BigNumber(1),
}),
];
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
const minValidSalt = new BigNumber(2);
const receipt = await zeroEx
.batchCancelPairRfqOrdersWithSigner(
contractWallet.address,
[makerToken.address, takerToken.address],
[takerToken.address, makerToken.address],
[minValidSalt, minValidSalt],
)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[
{
maker: contractWallet.address,
makerToken: makerToken.address,
takerToken: takerToken.address,
minValidSalt,
},
{
maker: contractWallet.address,
makerToken: takerToken.address,
takerToken: makerToken.address,
minValidSalt,
},
],
IZeroExEvents.PairCancelledRfqOrders,
);
const statuses = (await Promise.all(orders.map(o => zeroEx.getRfqOrderInfo(o).callAsync()))).map(
oi => oi.status,
);
expect(statuses).to.deep.eq([OrderStatus.Cancelled, OrderStatus.Cancelled]);
});
it(`doesn't allow an unapproved signer to batch cancel pair rfq orders`, async () => {
const minValidSalt = new BigNumber(2);
const tx = zeroEx
.batchCancelPairRfqOrdersWithSigner(
contractWallet.address,
[makerToken.address, takerToken.address],
[takerToken.address, makerToken.address],
[minValidSalt, minValidSalt],
)
.awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.InvalidSignerError(contractWallet.address, maker),
);
});
it(`allows a signer to cancel multiple limit order pairs`, async () => {
const orders = [
getTestLimitOrder({ maker: contractWallet.address, salt: new BigNumber(1) }),
// Flip the tokens for the other order.
getTestLimitOrder({
makerToken: takerToken.address,
takerToken: makerToken.address,
maker: contractWallet.address,
salt: new BigNumber(1),
}),
];
await contractWallet
.registerAllowedOrderSigner(contractWalletSigner, true)
.awaitTransactionSuccessAsync({ from: contractWalletOwner });
const minValidSalt = new BigNumber(2);
const receipt = await zeroEx
.batchCancelPairLimitOrdersWithSigner(
contractWallet.address,
[makerToken.address, takerToken.address],
[takerToken.address, makerToken.address],
[minValidSalt, minValidSalt],
)
.awaitTransactionSuccessAsync({ from: contractWalletSigner });
verifyEventsFromLogs(
receipt.logs,
[
{
maker: contractWallet.address,
makerToken: makerToken.address,
takerToken: takerToken.address,
minValidSalt,
},
{
maker: contractWallet.address,
makerToken: takerToken.address,
takerToken: makerToken.address,
minValidSalt,
},
],
IZeroExEvents.PairCancelledLimitOrders,
);
const statuses = (await Promise.all(orders.map(o => zeroEx.getLimitOrderInfo(o).callAsync()))).map(
oi => oi.status,
);
expect(statuses).to.deep.eq([OrderStatus.Cancelled, OrderStatus.Cancelled]);
});
it(`doesn't allow an unapproved signer to batch cancel pair limit orders`, async () => {
const minValidSalt = new BigNumber(2);
const tx = zeroEx
.batchCancelPairLimitOrdersWithSigner(
contractWallet.address,
[makerToken.address, takerToken.address],
[takerToken.address, makerToken.address],
[minValidSalt, minValidSalt],
)
.awaitTransactionSuccessAsync({ from: maker });
return expect(tx).to.revertWith(
new RevertErrors.NativeOrders.InvalidSignerError(contractWallet.address, maker),
);
});
});
});

View File

@@ -1,6 +1,5 @@
import { blockchainTests, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import * as ethjs from 'ethereumjs-util';
import { artifacts } from './artifacts';
import {
@@ -41,9 +40,9 @@ blockchainTests.resets('PermissionlessTransformerDeployer', env => {
it('deploys at predictable address', async () => {
const salt = hexUtils.random();
const targetAddress = await deployer.deploy(deployBytes, salt).callAsync();
const initCodeHash = hexUtils.toHex(ethjs.sha3(deployBytes));
const initCodeHash = hexUtils.hash(deployBytes);
const expectedAddress = hexUtils.slice(
hexUtils.toHex(ethjs.sha3(hexUtils.concat('0xFF', deployer.address, salt, initCodeHash))),
hexUtils.hash(hexUtils.concat('0xFF', deployer.address, salt, initCodeHash)),
12,
);
@@ -94,7 +93,7 @@ blockchainTests.resets('PermissionlessTransformerDeployer', env => {
const targetAddress = await deployer.deploy(deployBytes, salt).callAsync({ from: sender });
await deployer.deploy(deployBytes, salt).awaitTransactionSuccessAsync({ from: sender });
expect(hexUtils.toHex(await deployer.toInitCodeHash(targetAddress).callAsync())).to.eq(
hexUtils.toHex(ethjs.sha3(deployBytes)),
hexUtils.hash(deployBytes),
);
});
});

View File

@@ -125,6 +125,7 @@ export * from '../test/generated-wrappers/test_mint_token_erc20_transformer';
export * from '../test/generated-wrappers/test_mintable_erc20_token';
export * from '../test/generated-wrappers/test_mooniswap';
export * from '../test/generated-wrappers/test_native_orders_feature';
export * from '../test/generated-wrappers/test_order_signer_registry_with_contract_wallet';
export * from '../test/generated-wrappers/test_permissionless_transformer_deployer_suicidal';
export * from '../test/generated-wrappers/test_permissionless_transformer_deployer_transformer';
export * from '../test/generated-wrappers/test_rfq_origin_registration';

View File

@@ -156,6 +156,7 @@
"test/generated-artifacts/TestMintableERC20Token.json",
"test/generated-artifacts/TestMooniswap.json",
"test/generated-artifacts/TestNativeOrdersFeature.json",
"test/generated-artifacts/TestOrderSignerRegistryWithContractWallet.json",
"test/generated-artifacts/TestPermissionlessTransformerDeployerSuicidal.json",
"test/generated-artifacts/TestPermissionlessTransformerDeployerTransformer.json",
"test/generated-artifacts/TestRfqOriginRegistration.json",

View File

@@ -53,6 +53,8 @@ illustrates how events are emitted when trading through the Exchange Proxy.
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `RfqOrderOriginsAllowed`_ | Emitted when a tx.origin is added/removed for RFQ, via `registerAllowedRfqOrigins <./functions.html#registerallowedrfqorigins>`_ | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `OrderSignerRegistered`_ | Emitted when an order signer is added/removed for a maker, via `registerAllowedOrderSigner <./functions.html#registerallowedordersigner>`_ | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `TransformedERC20`_ | Emitted when an `ERC20 Transformation <../advanced/erc20_transformations.html>`_ completes. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `TransformerDeployerUpdated`_ | Emitted when the Transformer Deployer is upgraded. | ExchangeProxy |
@@ -227,7 +229,7 @@ PairCancelledLimitOrders
);
PairCancelledRfqOrders
------------------------
----------------------
.. code-block:: solidity
@@ -311,6 +313,21 @@ RfqOrderOriginsAllowed
bool allowed
);
OrderSignerRegistered
-------------------------
.. code-block:: solidity
/// @dev Emitted when new order signers are registered
/// @param maker The maker address that is registering a designated signer.
/// @param signer The address that will sign on behalf of maker.
/// @param allowed Indicates whether the address should be allowed.
event OrderSignerRegistered(
address maker,
address signer,
bool allowed
);
TransformedERC20
----------------

View File

@@ -4,54 +4,69 @@ Basic Functionality
Below is a catalog of basic Exchange functionality. For more advanced usage, like meta-transactions and dex aggregation, see the Advanced section.
+---------------------------------+--------------------------------------------------------------------------+
| **Limit Orders** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `fillLimitOrder`_ | Fills a Limit Order up to the amount requested. |
+---------------------------------+--------------------------------------------------------------------------+
| `fillOrKillLimitOrder`_ | Fills exactly the amount requested or reverts. |
+---------------------------------+--------------------------------------------------------------------------+
| `cancelLimitOrder`_ | Cancels an order so that it can no longer be filled. |
+---------------------------------+--------------------------------------------------------------------------+
| `batchCancelLimitOrders`_ | A batch call to `cancelLimitOrder`. |
+---------------------------------+--------------------------------------------------------------------------+
| `cancelPairLimitOrders`_ | Cancels Limit orders in a specific market pair. |
| | Ex: Cancel all Limit Orders selling WETH for USDC. |
+---------------------------------+--------------------------------------------------------------------------+
| `batchCancelPairLimitOrders`_ | A batch call to `cancelPairLimitOrders`. |
+---------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderInfo`_ | Returns the state of a given order. |
+---------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderHash`_ | Returns the EIP-712 hash for an order. |
+---------------------------------+--------------------------------------------------------------------------+
| **RFQ Orders** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `fillRfqOrder`_ | These are analogous to the above LimitOrder functions. |
+---------------------------------+ |
| `fillOrKillRfqOrder`_ | |
+---------------------------------+ |
| `cancelRfqOrder`_ | |
+---------------------------------+ |
| `batchCancelRfqOrders`_ | |
+---------------------------------+ |
| `cancelPairRfqOrders`_ | |
+---------------------------------+ |
| `batchCancelPairRfqOrders`_ | |
+---------------------------------+ |
| `getRfqOrderInfo`_ | |
+---------------------------------+ |
| `getRfqOrderHash`_ | |
+---------------------------------+--------------------------------------------------------------------------+
| `registerAllowedRfqOrigins`_ | Register tx.origin addresses that are allowed to fill an RFQ order. |
+---------------------------------+--------------------------------------------------------------------------+
| **Protocol Fees** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `getProtocolFeeMultiplier`_ | Takers of limit orders pay a protocol fee of `Multiplier * tx.gasprice`. |
| | This returns the `Multiplier`. |
+---------------------------------+--------------------------------------------------------------------------+
| `transferProtocolFeesForPools`_ | Transfers protocol fees from escrow to the 0x Staking System. |
| | This should be called near the end of each epoch. |
+---------------------------------+--------------------------------------------------------------------------+
+-----------------------------------------+--------------------------------------------------------------------------+
| **Limit Orders** | **Overview** |
+-----------------------------------------+--------------------------------------------------------------------------+
| `fillLimitOrder`_ | Fills a Limit Order up to the amount requested. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `fillOrKillLimitOrder`_ | Fills exactly the amount requested or reverts. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `cancelLimitOrder`_ | Cancels an order so that it can no longer be filled. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `batchCancelLimitOrders`_ | A batch call to `cancelLimitOrder`. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `cancelPairLimitOrders`_ | Cancels Limit orders in a specific market pair. |
| | Ex: Cancel all Limit Orders selling WETH for USDC. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `cancelPairLimitOrdersWithSigner`_ | Same functionality to ``cancelPairLimitOrders`` but called by a |
| | registered order signer instead of the maker itself. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `batchCancelPairLimitOrders`_ | A batch call to `cancelPairLimitOrders`. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `batchCancelPairLimitOrdersWithSigner`_ | Same functionality to ``cancelPairLimitOrders`` but called by a |
| | registered order signer instead of the maker itself. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderInfo`_ | Returns the state of a given order. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderHash`_ | Returns the EIP-712 hash for an order. |
+-----------------------------------------+--------------------------------------------------------------------------+
| **RFQ Orders** | **Overview** |
+-----------------------------------------+--------------------------------------------------------------------------+
| `fillRfqOrder`_ | These are analogous to the above LimitOrder functions. |
+-----------------------------------------+ |
| `fillOrKillRfqOrder`_ | |
+-----------------------------------------+ |
| `cancelRfqOrder`_ | |
+-----------------------------------------+ |
| `batchCancelRfqOrders`_ | |
+-----------------------------------------+ |
| `cancelPairRfqOrders`_ | |
+-----------------------------------------+ |
| `cancelPairRfqOrdersWithSigner`_ | |
+-----------------------------------------+ |
| `batchCancelPairRfqOrders`_ | |
+-----------------------------------------+ |
| `batchCancelPairRfqOrdersWithSigner`_ | |
+-----------------------------------------+ |
| `getRfqOrderInfo`_ | |
+-----------------------------------------+ |
| `getRfqOrderHash`_ | |
+-----------------------------------------+--------------------------------------------------------------------------+
| `registerAllowedRfqOrigins`_ | Register tx.origin addresses that are allowed to fill an RFQ order. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `registerAllowedOrderSigner`_ | Register addresses that can sign orders on behalf of ``msg.sender``. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `isValidOrderSigner`_ | Returns whether a given address is allowed to sign orders for a given |
| | maker address. |
+-----------------------------------------+--------------------------------------------------------------------------+
| **Protocol Fees** | **Overview** |
+-----------------------------------------+--------------------------------------------------------------------------+
| `getProtocolFeeMultiplier`_ | Takers of limit orders pay a protocol fee of `Multiplier * tx.gasprice`. |
| | This returns the `Multiplier`. |
+-----------------------------------------+--------------------------------------------------------------------------+
| `transferProtocolFeesForPools`_ | Transfers protocol fees from escrow to the 0x Staking System. |
| | This should be called near the end of each epoch. |
+-----------------------------------------+--------------------------------------------------------------------------+
Limit Orders
@@ -131,7 +146,7 @@ This function cancels a single limit order created by the caller:
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker`` or ``!isValidOrderSigner(maker, msg.sender)``.
batchCancelLimitOrders
----------------------
@@ -146,7 +161,7 @@ This function cancels multiple limit orders created by the caller:
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` or ``!isValidOrderSigner(maker, msg.sender)`` for any of the orders.
cancelPairLimitOrders
---------------------
@@ -162,10 +177,32 @@ This function cancels all limit orders created by the caller with with a maker a
)
external;
This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event, or reverts in one of the following scenarios:
This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event, or reverts if the ``salt`` parameter is ≤ to a previous ``salt``.
- ``msg.sender != order.maker``
- The ``salt`` parameter is ≤ to a previous ``salt``.
cancelPairLimitOrdersWithSigner
-------------------------------
Same functionality as ``cancelPairLimitOrders`` but ``msg.sender`` is a registered order signer instead of the maker itself.
.. code-block:: solidity
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
Reverts if ``!isValidOrderSigner(maker, msg.sender)``.
batchCancelPairLimitOrders
--------------------------
@@ -183,6 +220,31 @@ This function performs multiple ``cancelPairLimitOrders()`` at once. Each respec
This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
batchCancelPairLimitOrdersWithSigner
------------------------------------
Same functionality as ``batchCancelPairLimitOrders`` but ``msg.sender`` is a registered order signer instead of the maker itself.
.. code-block:: solidity
/// @dev Cancel all limit orders for a given maker and pairs with salts less
/// than the values provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
Reverts if ``!isValidOrderSigner(maker, msg.sender)``.
getLimitOrderInfo
-----------------
@@ -369,7 +431,7 @@ Similar to limit orders, RFQ orders can be cancelled on-chain through a variety
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker`` or ``!isValidOrderSigner(maker, msg.sender)``.
batchCancelRfqOrders
--------------------
@@ -384,7 +446,7 @@ This function cancels multiple RFQ orders created by the caller:
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` or ``!isValidOrderSigner(maker, msg.sender)`` for any orders for any of the orders.
cancelPairRfqOrders
-------------------
@@ -400,10 +462,32 @@ This function cancels all RFQ orders created by the caller with with a maker and
)
external;
This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event, or reverts in one of the following scenarios:
This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event, or reverts if the ``salt`` parameter is ≤ to a previous ``salt``.
- ``msg.sender != order.maker``
- The ``salt`` parameter is ≤ to a previous ``salt``.
cancelPairRfqOrdersWithSigner
-----------------------------
Same functionality as ``cancelPairRfqOrders`` but ``msg.sender`` is a registered order signer instead of the maker itself.
.. code-block:: solidity
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
Reverts if ``!isValidOrderSigner(maker, msg.sender)``.
batchCancelPairRfqOrders
------------------------
@@ -421,6 +505,31 @@ batchCancelPairRfqOrders
This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
batchCancelPairRfqOrdersWithSigner
----------------------------------
Same functionality as ``batchCancelPairRfqOrders`` but ``msg.sender`` is a registered order signer instead of the maker itself.
.. code-block:: solidity
/// @dev Cancel all RFQ orders for a given maker and pairs with salts less
/// than the values provided. The caller must be a signer registered to the maker.
/// Subsequent calls to this function with the same maker and pair require the
/// new salt to be >= the old salt.
/// @param maker The maker for which to cancel.
/// @param makerTokens The maker tokens.
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
Reverts if ``!isValidOrderSigner(maker, msg.sender)``.
getRfqOrderInfo
---------------
@@ -549,6 +658,47 @@ Looking at the 2nd use case, a maker can register valid tx origins using this fu
This function emits a `RfqOrderOriginsAllowed <../basics/events.html#rfqorderoriginsallowed>`_ event.
registerAllowedOrderSigner
--------------------------
Calls to fill functions require a signature provided by the maker. In cases where the signer can't be the maker itself (e.g. a contract wallet), the maker can delegate signing to another address.
To register a new delegated order signer, the maker can call ``registerAllowedOrderSigner`` with ``allowed == true``.
To revoke permission to a signer, the maker can call ``registerAllowedOrderSigner`` with ``allowed == false``.
.. code-block:: solidity
/// @dev Register a signer who can sign on behalf of msg.sender
/// This allows one to sign on behalf of a contract that calls this function
/// @param signer The address from which you plan to generate signatures
/// @param allowed True to register, false to unregister.
function registerAllowedOrderSigner(
address signer,
bool allowed
)
external;
This function emits an `OrderSignerRegistered <../basics/events.html#ordersignerregistered>`_ event.
isValidOrderSigner
------------------
Returns whether the ``signer`` is allowed to sign orders on behalf of the ``maker``.
.. code-block:: solidity
/// @dev checks if a given address is registered to sign on behalf of a maker address
/// @param maker The maker address encoded in an order (can be a contract)
/// @param signer The address that is providing a signature
function isValidOrderSigner(
address maker,
address signer
)
external
view
returns (bool isAllowed);
Protocol Fees
=============

View File

@@ -92,7 +92,7 @@ The ``RFQOrder`` struct has the following fields:
How To Sign
==============
Both Limit & RFQ orders must be signed by the `maker`. This signature is needed to fill an order, see `Basic Functionality <./functions.html>`_.
Both Limit & RFQ orders must be signed by the `maker` or a registered order signer (`registerAllowedOrderSigner <./functions.html#registerallowedrfqorigins>`_). This signature is needed to fill an order, see `Basic Functionality <./functions.html>`_.
The protocol accepts signatures defined by the following struct:

View File

@@ -4,7 +4,7 @@ Protocol Fees
An ETH protocol fee is paid by the Taker each time a `Limit Order <./orders.html#limit-orders>`_ is `filled <./functions.html>`_.
The fee is proportional to the gas cost of filling an order and scales linearly with gas price. The cost is currently ``70k * tx.gasprice``.
Every 10 days, these fees are aggregated and distributed to the makers as a liquidity reward: the reward is proportional to the maker's collected fees and staked ZRX relative to other makers.
At the end of every Staking Epoch, these fees are aggregated and distributed to the makers as a liquidity reward: the reward is proportional to the maker's collected fees and staked ZRX relative to other makers.
To learn more about protocol fees and liquidity incentives, see the `Official Spec <https://github.com/0xProject/0x-protocol-specification/blob/master/staking/staking-specification.md>`_.
.. note::

View File

@@ -66,7 +66,7 @@
"ignoreDependencyVersionsForPackage": "contract-wrappers"
},
"devDependencies": {
"@0x/monorepo-scripts": "^3.1.1",
"@0x/monorepo-scripts": "^3.1.6",
"@0x-lerna-fork/lerna": "3.16.10",
"@0xproject/npm-cli-login": "^0.0.11",
"async-child-process": "^1.1.1",

View File

@@ -1,7 +1,96 @@
[
{
"version": "6.8.0",
"changes": [
{
"note": "Prune paths which cannot improve the best path",
"pr": 183
},
{
"note": "Use FastABI for Sampler ABI encoding and decoding",
"pr": 183
}
],
"timestamp": 1619596077
},
{
"version": "6.7.0",
"changes": [
{
"note": "Support PancakeSwap V2",
"pr": 211
}
],
"timestamp": 1619481586
},
{
"version": "6.6.1",
"changes": [
{
"note": "Fixing Positive Slippage logic to not force the EP route",
"pr": 209
}
]
},
{
"version": "6.6.0",
"changes": [
{
"note": "Support `Ropsten` network",
"pr": 203
}
],
"timestamp": 1618592834
},
{
"version": "6.5.3",
"changes": [
{
"note": "Apply slippage to bridge orders in consumer",
"pr": 198
}
],
"timestamp": 1618433771
},
{
"timestamp": 1618314654,
"version": "6.5.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1618259868,
"version": "6.5.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "6.5.0",
"changes": [
{
"note": "Add Kyber DMM to Ethereum mainnet",
"pr": 194
},
{
"note": "Add default LiquidityProvider registry and allow LiquidityProvider gasCost to be a function of tokens",
"pr": 196
}
],
"timestamp": 1617913615
},
{
"version": "6.4.0",
"changes": [
{
"note": "Added Component, Smoothy, Saddle, Curve open pools, tweeks gas schedule, adding SushiSwap as a fee quote source",
"pr": 182
},
{
"note": "Use SOURCE_FLAGS.rfqOrder in comparisonPrice",
"pr": 177

View File

@@ -5,8 +5,43 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v6.8.0 - _April 28, 2021_
* Prune paths which cannot improve the best path (#183)
* Use FastABI for Sampler ABI encoding and decoding (#183)
## v6.7.0 - _April 26, 2021_
* Support PancakeSwap V2 (#211)
## v6.6.1 - _Invalid date_
* Fixing Positive Slippage logic to not force the EP route (#209)
## v6.6.0 - _April 16, 2021_
* Support `Ropsten` network (#203)
## v6.5.3 - _April 14, 2021_
* Apply slippage to bridge orders in consumer (#198)
## v6.5.2 - _April 13, 2021_
* Dependencies updated
## v6.5.1 - _April 12, 2021_
* Dependencies updated
## v6.5.0 - _April 8, 2021_
* Add Kyber DMM to Ethereum mainnet (#194)
* Add default LiquidityProvider registry and allow LiquidityProvider gasCost to be a function of tokens (#196)
## v6.4.0 - _April 1, 2021_
* Added Component, Smoothy, Saddle, Curve open pools, tweeks gas schedule, adding SushiSwap as a fee quote source (#182)
* Use SOURCE_FLAGS.rfqOrder in comparisonPrice (#177)
* Add a cancel token to ensure timeouts are respected (#176)
* Rename {Rfqt=>Rfq} for many types in Asset Swapper (#179)

View File

@@ -34,6 +34,7 @@ import "./MStableSampler.sol";
import "./MooniswapSampler.sol";
import "./NativeOrderSampler.sol";
import "./ShellSampler.sol";
import "./SmoothySampler.sol";
import "./TwoHopSampler.sol";
import "./UniswapSampler.sol";
import "./UniswapV2Sampler.sol";
@@ -55,6 +56,7 @@ contract ERC20BridgeSampler is
MultiBridgeSampler,
NativeOrderSampler,
ShellSampler,
SmoothySampler,
TwoHopSampler,
UniswapSampler,
UniswapV2Sampler,

View File

@@ -20,10 +20,20 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./ApproximateBuys.sol";
import "./interfaces/IShell.sol";
import "./SamplerUtils.sol";
contract ShellSampler
contract ShellSampler is
SamplerUtils,
ApproximateBuys
{
struct ShellInfo {
address poolAddress;
}
/// @dev Default gas limit for Shell calls.
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
@@ -56,10 +66,6 @@ contract ShellSampler
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
@@ -84,26 +90,37 @@ contract ShellSampler
view
returns (uint256[] memory takerTokenAmounts)
{
// Initialize array of maker token amounts.
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, pool),
takerTokenData: abi.encode(takerToken, pool),
getSellQuoteCallback: _sampleSellForApproximateBuyFromShell
}),
makerTokenAmounts
);
}
for (uint256 i = 0; i < numSamples; i++) {
try
IShell(pool).viewTargetSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, makerTokenAmounts[i])
returns (uint256 amount)
{
takerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
function _sampleSellForApproximateBuyFromShell(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address takerToken, address pool) = abi.decode(takerTokenData, (address, address));
(address makerToken) = abi.decode(makerTokenData, (address));
try
this.sampleSellsFromShell
(pool, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
}

View File

@@ -0,0 +1,156 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
// import "./interfaces/ISmoothy.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
import "./interfaces/ISmoothy.sol";
contract SmoothySampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Information for sampling from smoothy sources.
struct SmoothyInfo {
address poolAddress;
bytes4 sellQuoteFunctionSelector;
bytes4 buyQuoteFunctionSelector;
}
/// @dev Base gas limit for Smoothy calls.
uint256 constant private SMOOTHY_CALL_GAS = 600e3;
/// @dev Sample sell quotes from Smoothy.
/// @param smoothyInfo Smoothy information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromSmoothy(
SmoothyInfo memory smoothyInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
// Basically a Curve fork
// Smoothy only keep a percentage of its tokens available in reserve
uint256 poolReserveMakerAmount = ISmoothy(smoothyInfo.poolAddress).getBalance(uint256(toTokenIdx)) -
ISmoothy(smoothyInfo.poolAddress)._yBalances(uint256(toTokenIdx));
(, , , uint256 decimals) = ISmoothy(smoothyInfo.poolAddress).getTokenStats(uint256(toTokenIdx));
poolReserveMakerAmount = poolReserveMakerAmount/(10**(18-decimals));
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
smoothyInfo.poolAddress.staticcall.gas(SMOOTHY_CALL_GAS)(
abi.encodeWithSelector(
smoothyInfo.sellQuoteFunctionSelector,
fromTokenIdx,
toTokenIdx,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Make sure the quoted buyAmount is available in the pool reserve
if (buyAmount >= poolReserveMakerAmount) {
// Assign pool reserve amount for all higher samples to break early
for (uint256 j = i; j < numSamples; j++) {
makerTokenAmounts[j] = poolReserveMakerAmount;
}
break;
} else {
makerTokenAmounts[i] = buyAmount;
}
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Smoothy.
/// @param smoothyInfo Smoothy information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromSmoothy(
SmoothyInfo memory smoothyInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
// Buys not supported so approximate it.
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(toTokenIdx, smoothyInfo),
takerTokenData: abi.encode(fromTokenIdx, smoothyInfo),
getSellQuoteCallback: _sampleSellForApproximateBuyFromSmoothy
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromSmoothy(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(int128 takerTokenIdx, SmoothyInfo memory smoothyInfo) =
abi.decode(takerTokenData, (int128, SmoothyInfo));
(int128 makerTokenIdx) =
abi.decode(makerTokenData, (int128));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromSmoothy.selector,
smoothyInfo,
takerTokenIdx,
makerTokenIdx,
_toSingleValueArray(sellAmount)
));
if (!success) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface ISmoothy {
function getBalance (
uint256 tid
)
external
view
returns (uint256 balance);
function _yBalances (
uint256 tid
)
external
view
returns (uint256 balance);
function getTokenStats (
uint256 tid
)
external
view
returns (uint256 softWeight, uint256 hardWeight, uint256 balance, uint256 decimals);
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
"version": "6.4.0",
"version": "6.8.0",
"engines": {
"node": ">=6.12"
},
@@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json",
"postpublish": {
"assets": []
}
@@ -57,20 +57,20 @@
"registry": "git@github.com:0xProject/gitpkg-registry.git"
},
"dependencies": {
"@0x/assert": "^3.0.21",
"@0x/base-contract": "^6.2.18",
"@0x/assert": "^3.0.26",
"@0x/base-contract": "^6.4.0",
"@0x/contract-addresses": "^6.0.0",
"@0x/contract-wrappers": "^13.15.0",
"@0x/contracts-erc20": "^3.3.6",
"@0x/contracts-zero-ex": "^0.21.0",
"@0x/dev-utils": "^4.2.1",
"@0x/json-schemas": "^5.4.1",
"@0x/protocol-utils": "^1.4.0",
"@0x/contract-wrappers": "^13.16.0",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-zero-ex": "^0.22.1",
"@0x/dev-utils": "^4.2.6",
"@0x/json-schemas": "^6.1.2",
"@0x/protocol-utils": "^1.5.1",
"@0x/quote-server": "^5.0.0",
"@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6",
"@0x/utils": "^6.2.0",
"@0x/web3-wrapper": "^7.4.1",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",
"@0x/utils": "^6.4.2",
"@0x/web3-wrapper": "^7.5.2",
"@balancer-labs/sor": "0.3.2",
"@bancor/sdk": "0.2.9",
"@ethersproject/abi": "^5.0.1",
@@ -82,26 +82,27 @@
"axios-mock-adapter": "^1.19.0",
"cream-sor": "^0.3.3",
"decimal.js": "^10.2.0",
"ethereum-types": "^3.4.0",
"ethereumjs-util": "^5.1.1",
"ethereum-types": "^3.5.0",
"ethereumjs-util": "^7.0.10",
"fast-abi": "^0.0.2",
"heartbeats": "^5.0.1",
"lodash": "^4.17.11"
},
"devDependencies": {
"@0x/base-contract": "^6.2.18",
"@0x/contracts-asset-proxy": "^3.7.9",
"@0x/contracts-exchange": "^3.2.28",
"@0x/contracts-exchange-libs": "^4.3.27",
"@0x/contracts-gen": "^2.0.32",
"@0x/contracts-test-utils": "^5.3.24",
"@0x/contracts-utils": "^4.7.6",
"@0x/abi-gen": "^5.6.0",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-exchange": "^3.2.29",
"@0x/contracts-exchange-libs": "^4.3.28",
"@0x/contracts-gen": "^2.0.37",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/mesh-rpc-client": "^9.4.2",
"@0x/migrations": "^8.0.0",
"@0x/sol-compiler": "^4.6.1",
"@0x/subproviders": "^6.4.1",
"@0x/migrations": "^8.0.3",
"@0x/sol-compiler": "^4.7.2",
"@0x/subproviders": "^6.5.2",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3",
"@0x/types": "^3.3.1",
"@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.3",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "12.12.54",

View File

@@ -23,6 +23,7 @@ import {
CalldataInfo,
ExchangeProxyContractOpts,
MarketBuySwapQuote,
MarketOperation,
MarketSellSwapQuote,
SwapQuote,
SwapQuoteConsumerBase,
@@ -43,6 +44,7 @@ import {
LiquidityProviderFillData,
MooniswapFillData,
OptimizedMarketBridgeOrder,
OptimizedMarketOrder,
UniswapV2FillData,
} from '../utils/market_operation_utils/types';
@@ -136,7 +138,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
const buyToken = quote.makerToken;
// Take the bounds from the worst case
const sellAmount = quote.worstCaseQuoteInfo.totalTakerAmount;
const sellAmount = BigNumber.max(
quote.bestCaseQuoteInfo.totalTakerAmount,
quote.worstCaseQuoteInfo.totalTakerAmount,
);
let minBuyAmount = quote.worstCaseQuoteInfo.makerAmount;
let ethAmount = quote.worstCaseQuoteInfo.protocolFeeInWeiAmount;
@@ -144,13 +149,15 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
ethAmount = ethAmount.plus(sellAmount);
}
const slippedOrders = slipNonNativeOrders(quote);
// VIP routes.
if (
this.chainId === ChainId.Mainnet &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.UniswapV2, ERC20BridgeSource.SushiSwap])
) {
const source = quote.orders[0].source;
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
const source = slippedOrders[0].source;
const fillData = (slippedOrders[0] as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
return {
calldataHexString: this._exchangeProxy
.sellToUniswap(
@@ -183,8 +190,8 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
ERC20BridgeSource.SushiSwap,
])
) {
const source = quote.orders[0].source;
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
const source = slippedOrders[0].source;
const fillData = (slippedOrders[0] as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
return {
calldataHexString: this._exchangeProxy
.sellToPancakeSwap(
@@ -213,7 +220,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
this.chainId === ChainId.Mainnet &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.LiquidityProvider])
) {
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<LiquidityProviderFillData>).fillData;
const fillData = (slippedOrders[0] as OptimizedMarketBridgeOrder<LiquidityProviderFillData>).fillData;
const target = fillData.poolAddress;
return {
calldataHexString: this._exchangeProxy
@@ -238,7 +245,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
this.chainId === ChainId.Mainnet &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve, ERC20BridgeSource.Swerve])
) {
const fillData = quote.orders[0].fills[0].fillData as CurveFillData;
const fillData = slippedOrders[0].fills[0].fillData as CurveFillData;
return {
calldataHexString: this._exchangeProxy
.sellToLiquidityProvider(
@@ -267,7 +274,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
this.chainId === ChainId.Mainnet &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Mooniswap])
) {
const fillData = quote.orders[0].fills[0].fillData as MooniswapFillData;
const fillData = slippedOrders[0].fills[0].fillData as MooniswapFillData;
return {
calldataHexString: this._exchangeProxy
.sellToLiquidityProvider(
@@ -289,7 +296,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
if (this.chainId === ChainId.Mainnet && isMultiplexBatchFillCompatible(quote, optsWithDefaults)) {
return {
calldataHexString: this._encodeMultiplexBatchFillCalldata(quote),
calldataHexString: this._encodeMultiplexBatchFillCalldata({ ...quote, orders: slippedOrders }),
ethAmount,
toAddress: this._exchangeProxy.address,
allowanceTarget: this._exchangeProxy.address,
@@ -298,7 +305,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
}
if (this.chainId === ChainId.Mainnet && isMultiplexMultiHopFillCompatible(quote, optsWithDefaults)) {
return {
calldataHexString: this._encodeMultiplexMultiHopFillCalldata(quote, optsWithDefaults),
calldataHexString: this._encodeMultiplexMultiHopFillCalldata(
{ ...quote, orders: slippedOrders },
optsWithDefaults,
),
ethAmount,
toAddress: this._exchangeProxy.address,
allowanceTarget: this._exchangeProxy.address,
@@ -321,10 +331,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
// If it's two hop we have an intermediate token this is needed to encode the individual FQT
// and we also want to ensure no dust amount is left in the flash wallet
const intermediateToken = quote.isTwoHop ? quote.orders[0].makerToken : NULL_ADDRESS;
const intermediateToken = quote.isTwoHop ? slippedOrders[0].makerToken : NULL_ADDRESS;
// This transformer will fill the quote.
if (quote.isTwoHop) {
const [firstHopOrder, secondHopOrder] = quote.orders;
const [firstHopOrder, secondHopOrder] = slippedOrders;
transforms.push({
deploymentNonce: this.transformerNonces.fillQuoteTransformer,
data: encodeFillQuoteTransformerData({
@@ -349,14 +359,13 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
});
} else {
const fillAmount = isBuyQuote(quote) ? quote.makerTokenFillAmount : quote.takerTokenFillAmount;
transforms.push({
deploymentNonce: this.transformerNonces.fillQuoteTransformer,
data: encodeFillQuoteTransformerData({
side: isBuyQuote(quote) ? FillQuoteTransformerSide.Buy : FillQuoteTransformerSide.Sell,
sellToken,
buyToken,
...getFQTTransformerDataFromOptimizedOrders(quote.orders),
...getFQTTransformerDataFromOptimizedOrders(slippedOrders),
refundReceiver: refundReceiver || NULL_ADDRESS,
fillAmount: !isBuyQuote(quote) && shouldSellEntireBalance ? MAX_UINT256 : fillAmount,
}),
@@ -598,3 +607,38 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
.getABIEncodedTransactionData();
}
}
function slipNonNativeOrders(quote: MarketSellSwapQuote | MarketBuySwapQuote): OptimizedMarketOrder[] {
const slippage = getMaxQuoteSlippageRate(quote);
if (!slippage) {
return quote.orders;
}
return quote.orders.map(o => {
if (o.source === ERC20BridgeSource.Native) {
return o;
}
return {
...o,
...(quote.type === MarketOperation.Sell
? { makerAmount: o.makerAmount.times(1 - slippage).integerValue(BigNumber.ROUND_DOWN) }
: { takerAmount: o.takerAmount.times(1 + slippage).integerValue(BigNumber.ROUND_UP) }),
};
});
}
function getMaxQuoteSlippageRate(quote: MarketBuySwapQuote | MarketSellSwapQuote): number {
if (quote.type === MarketOperation.Buy) {
// (worstCaseTaker - bestCaseTaker) / bestCaseTaker
// where worstCaseTaker >= bestCaseTaker
return quote.worstCaseQuoteInfo.takerAmount
.minus(quote.bestCaseQuoteInfo.takerAmount)
.div(quote.bestCaseQuoteInfo.takerAmount)
.toNumber();
}
// (bestCaseMaker - worstCaseMaker) / bestCaseMaker
// where bestCaseMaker >= worstCaseMaker
return quote.bestCaseQuoteInfo.makerAmount
.minus(quote.worstCaseQuoteInfo.makerAmount)
.div(quote.bestCaseQuoteInfo.makerAmount)
.toNumber();
}

View File

@@ -1,6 +1,6 @@
import { FillQuoteTransformerData, FillQuoteTransformerOrderType } from '@0x/protocol-utils';
import { AffiliateFeeType, ExchangeProxyContractOpts, MarketBuySwapQuote, MarketOperation, SwapQuote } from '../types';
import { ExchangeProxyContractOpts, MarketBuySwapQuote, MarketOperation, SwapQuote } from '../types';
import {
createBridgeDataForBridgeOrder,
getErc20BridgeSourceToBridgeSource,
@@ -70,6 +70,7 @@ export function isMultiplexMultiHopFillCompatible(quote: SwapQuote, opts: Exchan
/**
* Returns true iff a quote can be filled via a VIP feature.
*/
export function isDirectSwapCompatible(
quote: SwapQuote,
opts: ExchangeProxyContractOpts,
@@ -163,10 +164,6 @@ export function requiresTransformERC20(opts: ExchangeProxyContractOpts): boolean
if (!opts.affiliateFee.buyTokenFeeAmount.eq(0) || !opts.affiliateFee.sellTokenFeeAmount.eq(0)) {
return true;
}
// Has a positive slippage fee.
if (opts.affiliateFee.feeType === AffiliateFeeType.PositiveSlippageFee) {
return true;
}
// VIP does not support selling the entire balance
if (opts.shouldSellEntireBalance) {
return true;

View File

@@ -2,7 +2,8 @@ import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addre
import { FillQuoteTransformerOrderType, LimitOrder } from '@0x/protocol-utils';
import { BigNumber, providerUtils } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios';
import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import { BlockParamLiteral, MethodAbi, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import { FastABI } from 'fast-abi';
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';
import * as _ from 'lodash';
@@ -122,12 +123,19 @@ export class SwapQuoter {
{ block: BlockParamLiteral.Latest, overrides: defaultCodeOverrides },
options.samplerOverrides,
);
const fastAbi = new FastABI(ERC20BridgeSamplerContract.ABI() as MethodAbi[]);
const samplerContract = new ERC20BridgeSamplerContract(
this._contractAddresses.erc20BridgeSampler,
this.provider,
{
gas: samplerGasLimit,
},
{},
undefined,
{
encodeInput: (fnName: string, values: any) => fastAbi.encodeInput(fnName, values),
decodeOutput: (fnName: string, data: string) => fastAbi.decodeOutput(fnName, data),
},
);
this._marketOperationUtils = new MarketOperationUtils(
@@ -591,9 +599,10 @@ function calculateTwoHopQuoteInfo(
: secondHopOrder.makerAmount,
takerAmount: MarketOperation.Sell
? firstHopOrder.takerAmount
: // tslint:disable-next-line: binary-expression-operand-order
firstHopOrder.takerAmount.times(1 + slippage).integerValue(),
totalTakerAmount: firstHopOrder.takerAmount,
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(),
totalTakerAmount: MarketOperation.Sell
? firstHopOrder.takerAmount
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(),
feeTakerTokenAmount: constants.ZERO_AMOUNT,
protocolFeeInWeiAmount: constants.ZERO_AMOUNT,
gas,

View File

@@ -3,11 +3,11 @@ import { SDK } from '@bancor/sdk';
import { Ethereum } from '@bancor/sdk/dist/blockchains/ethereum';
import { BlockchainType } from '@bancor/sdk/dist/types';
import { TOKENS } from './constants';
import { MAINNET_TOKENS } from './constants';
const findToken = (tokenAddress: string, graph: object): string =>
// If we're looking for WETH it is stored by Bancor as the 0xeee address
tokenAddress.toLowerCase() === TOKENS.WETH.toLowerCase()
tokenAddress.toLowerCase() === MAINNET_TOKENS.WETH.toLowerCase()
? '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
: Object.keys(graph).filter(k => k.toLowerCase() === tokenAddress.toLowerCase())[0];

View File

@@ -4,19 +4,25 @@ import { BigNumber, NULL_BYTES } from '@0x/utils';
import {
BAKERYSWAP_ROUTER_BY_CHAIN_ID,
BELT_BSC_INFOS,
COMPONENT_POOLS_BY_CHAIN_ID,
CRYPTO_COM_ROUTER_BY_CHAIN_ID,
CURVE_MAINNET_INFOS,
ELLIPSIS_BSC_INFOS,
KYBER_BRIDGED_LIQUIDITY_PREFIX,
MAINNET_CURVE_INFOS,
MAINNET_SNOWSWAP_INFOS,
MAINNET_SWERVE_INFOS,
KYBER_DMM_ROUTER_BY_CHAIN_ID,
MAX_DODOV2_POOLS_QUERIED,
MAX_KYBER_RESERVES_QUERIED,
NERVE_BSC_INFOS,
NULL_ADDRESS,
PANCAKESWAP_ROUTER_BY_CHAIN_ID,
PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID,
SADDLE_MAINNET_INFOS,
SHELL_POOLS_BY_CHAIN_ID,
SMOOTHY_BSC_INFOS,
SMOOTHY_MAINNET_INFOS,
SNOWSWAP_MAINNET_INFOS,
SUSHISWAP_ROUTER_BY_CHAIN_ID,
SWERVE_MAINNET_INFOS,
UNISWAPV2_ROUTER_BY_CHAIN_ID,
} from './constants';
import { CurveInfo, ERC20BridgeSource } from './types';
@@ -60,12 +66,22 @@ export function getShellsForPair(chainId: ChainId, takerToken: string, makerToke
.map(i => i.poolAddress);
}
// tslint:disable completed-docs
export function getComponentForPair(chainId: ChainId, takerToken: string, makerToken: string): string[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(COMPONENT_POOLS_BY_CHAIN_ID[chainId])
.filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)))
.map(i => i.poolAddress);
}
// tslint:disable completed-docs
export function getCurveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(MAINNET_CURVE_INFOS).filter(c =>
return Object.values(CURVE_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
@@ -78,7 +94,7 @@ export function getSwerveInfosForPair(chainId: ChainId, takerToken: string, make
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(MAINNET_SWERVE_INFOS).filter(c =>
return Object.values(SWERVE_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
@@ -91,7 +107,7 @@ export function getSnowSwapInfosForPair(chainId: ChainId, takerToken: string, ma
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(MAINNET_SNOWSWAP_INFOS).filter(c =>
return Object.values(SNOWSWAP_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
@@ -139,6 +155,61 @@ export function getEllipsisInfosForPair(chainId: ChainId, takerToken: string, ma
);
}
export function getSmoothyInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId === ChainId.BSC) {
return Object.values(SMOOTHY_BSC_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) &&
c.metaToken !== undefined &&
[makerToken, takerToken].includes(c.metaToken)),
),
);
} else if (chainId === ChainId.Mainnet) {
return Object.values(SMOOTHY_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) &&
c.metaToken !== undefined &&
[makerToken, takerToken].includes(c.metaToken)),
),
);
} else {
return [];
}
}
export function getSaddleInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(SADDLE_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
),
);
}
export function getShellLikeInfosForPair(
chainId: ChainId,
takerToken: string,
makerToken: string,
source: ERC20BridgeSource.Shell | ERC20BridgeSource.Component,
): string[] {
switch (source) {
case ERC20BridgeSource.Shell:
return getShellsForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.Component:
return getComponentForPair(chainId, takerToken, makerToken);
default:
throw new Error(`Unknown Shell like source ${source}`);
}
}
export function getCurveLikeInfosForPair(
chainId: ChainId,
takerToken: string,
@@ -149,7 +220,9 @@ export function getCurveLikeInfosForPair(
| ERC20BridgeSource.SnowSwap
| ERC20BridgeSource.Nerve
| ERC20BridgeSource.Belt
| ERC20BridgeSource.Ellipsis,
| ERC20BridgeSource.Ellipsis
| ERC20BridgeSource.Smoothy
| ERC20BridgeSource.Saddle,
): CurveInfo[] {
switch (source) {
case ERC20BridgeSource.Curve:
@@ -164,6 +237,10 @@ export function getCurveLikeInfosForPair(
return getBeltInfosForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.Ellipsis:
return getEllipsisInfosForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.Smoothy:
return getSmoothyInfosForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.Saddle:
return getSaddleInfosForPair(chainId, takerToken, makerToken);
default:
throw new Error(`Unknown Curve like source ${source}`);
}
@@ -176,7 +253,9 @@ export function uniswapV2LikeRouterAddress(
| ERC20BridgeSource.SushiSwap
| ERC20BridgeSource.CryptoCom
| ERC20BridgeSource.PancakeSwap
| ERC20BridgeSource.BakerySwap,
| ERC20BridgeSource.BakerySwap
| ERC20BridgeSource.KyberDmm
| ERC20BridgeSource.PancakeSwapV2,
): string {
switch (source) {
case ERC20BridgeSource.UniswapV2:
@@ -189,6 +268,10 @@ export function uniswapV2LikeRouterAddress(
return PANCAKESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.BakerySwap:
return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.KyberDmm:
return KYBER_DMM_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.PancakeSwapV2:
return PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID[chainId];
default:
throw new Error(`Unknown UniswapV2 like source ${source}`);
}

View File

@@ -152,7 +152,7 @@ function dexSamplesToFills(
const { source, fillData } = sample;
const input = sample.input.minus(prevSample ? prevSample.input : 0);
const output = sample.output.minus(prevSample ? prevSample.output : 0);
const fee = fees[source] === undefined ? 0 : fees[source]!(sample.fillData);
const fee = fees[source] === undefined ? 0 : fees[source]!(sample.fillData) || 0;
let penalty = ZERO_AMOUNT;
if (i === 0) {
// Only the first fill in a DEX path incurs a penalty.

View File

@@ -5,8 +5,22 @@ export function getLiquidityProvidersForPair(
registry: LiquidityProviderRegistry,
takerToken: string,
makerToken: string,
): string[] {
): Array<{ providerAddress: string; gasCost: number }> {
return Object.entries(registry)
.filter(([, plp]) => [makerToken, takerToken].every(t => plp.tokens.includes(t)))
.map(([providerAddress]) => providerAddress);
.map(([providerAddress]) => {
let gasCost: number;
if (typeof registry[providerAddress].gasCost === 'number') {
gasCost = registry[providerAddress].gasCost as number;
} else {
gasCost = (registry[providerAddress].gasCost as (takerToken: string, makerToken: string) => number)(
takerToken,
makerToken,
);
}
return {
providerAddress,
gasCost,
};
});
}

View File

@@ -89,6 +89,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo');
case ERC20BridgeSource.Kyber:
return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber');
case ERC20BridgeSource.KyberDmm:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'KyberDmm');
case ERC20BridgeSource.LiquidityProvider:
// "LiquidityProvider" is too long to encode (17 characters).
return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP');
@@ -126,6 +128,14 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Belt');
case ERC20BridgeSource.Ellipsis:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Ellipsis');
case ERC20BridgeSource.Component:
return encodeBridgeSourceId(BridgeProtocol.Shell, 'Component');
case ERC20BridgeSource.Smoothy:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Smoothy');
case ERC20BridgeSource.Saddle:
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'Saddle');
case ERC20BridgeSource.PancakeSwapV2:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwapV2');
default:
throw new Error(AggregationError.NoBridgeForSource);
}
@@ -153,6 +163,8 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Belt:
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Smoothy:
case ERC20BridgeSource.Saddle:
const curveFillData = (order as OptimizedMarketBridgeOrder<CurveFillData>).fillData;
bridgeData = encoder.encode([
curveFillData.pool.poolAddress,
@@ -176,6 +188,8 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.Linkswap:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
break;
@@ -200,6 +214,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
bridgeData = encoder.encode([dodoV2FillData.poolAddress, dodoV2FillData.isSellBase]);
break;
case ERC20BridgeSource.Shell:
case ERC20BridgeSource.Component:
const shellFillData = (order as OptimizedMarketBridgeOrder<ShellFillData>).fillData;
bridgeData = encoder.encode([shellFillData.poolAddress]);
break;
@@ -299,14 +314,18 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Nerve]: curveEncoder,
[ERC20BridgeSource.Belt]: curveEncoder,
[ERC20BridgeSource.Ellipsis]: curveEncoder,
[ERC20BridgeSource.Smoothy]: curveEncoder,
[ERC20BridgeSource.Saddle]: curveEncoder,
// UniswapV2 like, (router, address[])
[ERC20BridgeSource.Bancor]: routerAddressPathEncoder,
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
[ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder,
[ERC20BridgeSource.Linkswap]: routerAddressPathEncoder,
[ERC20BridgeSource.KyberDmm]: routerAddressPathEncoder,
// Generic pools
[ERC20BridgeSource.Shell]: poolEncoder,
[ERC20BridgeSource.Component]: poolEncoder,
[ERC20BridgeSource.Mooniswap]: poolEncoder,
[ERC20BridgeSource.Eth2Dai]: poolEncoder,
[ERC20BridgeSource.MStable]: poolEncoder,
@@ -318,6 +337,7 @@ export const BRIDGE_ENCODERS: {
// BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder,
[ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
};
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {

View File

@@ -152,6 +152,17 @@ export class Path {
return getRate(this.side, input, output);
}
/**
* Returns the best possible rate this path can offer, given the fills.
*/
public bestRate(): BigNumber {
const best = this.fills.reduce((prevRate, curr) => {
const currRate = getRate(this.side, curr.input, curr.output);
return prevRate.isLessThan(currRate) ? currRate : prevRate;
}, new BigNumber(0));
return best;
}
public adjustedSlippage(maxRate: BigNumber): number {
if (maxRate.eq(0)) {
return 0;

View File

@@ -4,7 +4,7 @@ import * as _ from 'lodash';
import { MarketOperation } from '../../types';
import { DEFAULT_PATH_PENALTY_OPTS, Path, PathPenaltyOpts } from './path';
import { Fill } from './types';
import { ERC20BridgeSource, Fill } from './types';
// tslint:disable: prefer-for-of custom-no-magic-numbers completed-docs no-bitwise
@@ -22,12 +22,13 @@ export async function findOptimalPathAsync(
opts: PathPenaltyOpts = DEFAULT_PATH_PENALTY_OPTS,
): Promise<Path | undefined> {
// Sort fill arrays by descending adjusted completed rate.
const sortedPaths = fillsToSortedPaths(fills, side, targetInput, opts);
// Remove any paths which cannot impact the optimal path
const sortedPaths = reducePaths(fillsToSortedPaths(fills, side, targetInput, opts), side);
if (sortedPaths.length === 0) {
return undefined;
}
const rates = rateBySourcePathId(sortedPaths);
let optimalPath = sortedPaths[0];
const rates = rateBySourcePathId(side, fills, targetInput);
for (const [i, path] of sortedPaths.slice(1).entries()) {
optimalPath = mixPaths(side, optimalPath, path, targetInput, runLimit * RUN_LIMIT_DECAY_FACTOR ** i, rates);
// Yield to event loop.
@@ -44,10 +45,47 @@ export function fillsToSortedPaths(
opts: PathPenaltyOpts,
): Path[] {
const paths = fills.map(singleSourceFills => Path.create(side, singleSourceFills, targetInput, opts));
const sortedPaths = paths.sort((a, b) => b.adjustedCompleteRate().comparedTo(a.adjustedCompleteRate()));
const sortedPaths = paths.sort((a, b) => {
const aRate = a.adjustedCompleteRate();
const bRate = b.adjustedCompleteRate();
// There is a case where the adjusted completed rate isn't sufficient for the desired amount
// resulting in a NaN div by 0 (output)
if (bRate.isNaN()) {
return -1;
}
if (aRate.isNaN()) {
return 1;
}
return bRate.comparedTo(aRate);
});
return sortedPaths;
}
// Remove paths which have no impact on the optimal path
export function reducePaths(sortedPaths: Path[], side: MarketOperation): Path[] {
// Any path which has a min rate that is less than the best adjusted completed rate has no chance of improving
// the overall route.
const bestNonNativeCompletePath = sortedPaths.filter(
p => p.isComplete() && p.fills[0].source !== ERC20BridgeSource.Native,
)[0];
// If there is no complete path then just go ahead with the sorted paths
// I.e if the token only exists on sources which cannot sell to infinity
// or buys where X is greater than all the tokens available in the pools
if (!bestNonNativeCompletePath) {
return sortedPaths;
}
const bestNonNativeCompletePathAdjustedRate = bestNonNativeCompletePath.adjustedCompleteRate();
if (!bestNonNativeCompletePathAdjustedRate.isGreaterThan(0)) {
return sortedPaths;
}
const filteredPaths = sortedPaths.filter(p =>
p.bestRate().isGreaterThanOrEqualTo(bestNonNativeCompletePathAdjustedRate),
);
return filteredPaths;
}
function mixPaths(
side: MarketOperation,
pathA: Path,
@@ -98,17 +136,6 @@ function mixPaths(
return bestPath;
}
function rateBySourcePathId(
side: MarketOperation,
fills: Fill[][],
targetInput: BigNumber,
): { [id: string]: BigNumber } {
const flattenedFills = _.flatten(fills);
const sourcePathIds = flattenedFills.filter(f => f.index === 0).map(f => f.sourcePathId);
return Object.assign(
{},
...sourcePathIds.map(s => ({
[s]: Path.create(side, flattenedFills.filter(f => f.sourcePathId === s), targetInput).adjustedRate(),
})),
);
function rateBySourcePathId(paths: Path[]): { [id: string]: BigNumber } {
return _.fromPairs(paths.map(p => [p.fills[0].sourcePathId, p.adjustedRate()]));
}

View File

@@ -12,7 +12,7 @@ import {
getCurveLikeInfosForPair,
getDodoV2Offsets,
getKyberOffsets,
getShellsForPair,
getShellLikeInfosForPair,
isAllowedKyberReserveId,
isBadTokenForSource,
isValidAddress,
@@ -24,7 +24,8 @@ import {
DODOV2_FACTORIES_BY_CHAIN_ID,
KYBER_CONFIG_BY_CHAIN_ID,
LINKSWAP_ROUTER_BY_CHAIN_ID,
LIQUIDITY_PROVIDER_REGISTRY,
LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID,
MAINNET_TOKENS,
MAKER_PSM_INFO_BY_CHAIN_ID,
MAX_UINT256,
MOONISWAP_REGISTRIES_BY_CHAIN_ID,
@@ -34,7 +35,6 @@ import {
NULL_BYTES,
OASIS_ROUTER_BY_CHAIN_ID,
SELL_SOURCE_FILTER_BY_CHAIN_ID,
TOKENS,
UNISWAPV1_ROUTER_BY_CHAIN_ID,
ZERO_AMOUNT,
} from './constants';
@@ -87,6 +87,7 @@ export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSour
* for use with `DexOrderSampler.executeAsync()`.
*/
export class SamplerOperations {
public readonly liquidityProviderRegistry: LiquidityProviderRegistry;
protected _bancorService?: BancorService;
public static constant<T>(result: T): BatchedOperation<T> {
return {
@@ -102,9 +103,13 @@ export class SamplerOperations {
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(),
protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] },
public readonly liquidityProviderRegistry: LiquidityProviderRegistry = LIQUIDITY_PROVIDER_REGISTRY,
liquidityProviderRegistry: LiquidityProviderRegistry = {},
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
) {
this.liquidityProviderRegistry = {
...LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID[chainId],
...liquidityProviderRegistry,
};
// Initialize the Bancor service, fetching paths in the background
bancorServiceFn()
.then(service => (this._bancorService = service))
@@ -136,6 +141,13 @@ export class SamplerOperations {
orders: SignedNativeOrder[],
exchangeAddress: string,
): BatchedOperation<BigNumber[]> {
// Skip checking empty or invalid orders on-chain, returning a constant
if (orders.length === 0) {
return SamplerOperations.constant<BigNumber[]>([]);
}
if (orders.length === 1 && orders[0].order.maker === NULL_ADDRESS) {
return SamplerOperations.constant<BigNumber[]>([ZERO_AMOUNT]);
}
return new SamplerContractOperation({
source: ERC20BridgeSource.Native,
contract: this._samplerContract,
@@ -149,6 +161,13 @@ export class SamplerOperations {
orders: SignedNativeOrder[],
exchangeAddress: string,
): BatchedOperation<BigNumber[]> {
// Skip checking empty or invalid orders on-chain, returning a constant
if (orders.length === 0) {
return SamplerOperations.constant<BigNumber[]>([]);
}
if (orders.length === 1 && orders[0].order.maker === NULL_ADDRESS) {
return SamplerOperations.constant<BigNumber[]>([ZERO_AMOUNT]);
}
return new SamplerContractOperation({
source: ERC20BridgeSource.Native,
contract: this._samplerContract,
@@ -277,12 +296,13 @@ export class SamplerOperations {
makerToken: string,
takerToken: string,
takerFillAmounts: BigNumber[],
gasCost: number,
): SourceQuoteOperation<LiquidityProviderFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.LiquidityProvider,
fillData: {
poolAddress: providerAddress,
gasCost: this.liquidityProviderRegistry[providerAddress].gasCost,
gasCost,
},
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromLiquidityProvider,
@@ -295,12 +315,13 @@ export class SamplerOperations {
makerToken: string,
takerToken: string,
makerFillAmounts: BigNumber[],
gasCost: number,
): SourceQuoteOperation<LiquidityProviderFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.LiquidityProvider,
fillData: {
poolAddress: providerAddress,
gasCost: this.liquidityProviderRegistry[providerAddress].gasCost,
gasCost,
},
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromLiquidityProvider,
@@ -396,6 +417,62 @@ export class SamplerOperations {
});
}
public getSmoothySellQuotes(
pool: CurveInfo,
fromTokenIdx: number,
toTokenIdx: number,
takerFillAmounts: BigNumber[],
): SourceQuoteOperation<CurveFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.Smoothy,
fillData: {
pool,
fromTokenIdx,
toTokenIdx,
},
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromSmoothy,
params: [
{
poolAddress: pool.poolAddress,
sellQuoteFunctionSelector: pool.sellQuoteFunctionSelector,
buyQuoteFunctionSelector: pool.buyQuoteFunctionSelector,
},
new BigNumber(fromTokenIdx),
new BigNumber(toTokenIdx),
takerFillAmounts,
],
});
}
public getSmoothyBuyQuotes(
pool: CurveInfo,
fromTokenIdx: number,
toTokenIdx: number,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<CurveFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.Smoothy,
fillData: {
pool,
fromTokenIdx,
toTokenIdx,
},
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromSmoothy,
params: [
{
poolAddress: pool.poolAddress,
sellQuoteFunctionSelector: pool.sellQuoteFunctionSelector,
buyQuoteFunctionSelector: pool.buyQuoteFunctionSelector,
},
new BigNumber(fromTokenIdx),
new BigNumber(toTokenIdx),
makerFillAmounts,
],
});
}
public getBalancerSellQuotes(
poolAddress: string,
makerToken: string,
@@ -743,9 +820,10 @@ export class SamplerOperations {
makerToken: string,
takerToken: string,
takerFillAmounts: BigNumber[],
source: ERC20BridgeSource = ERC20BridgeSource.Shell,
): SourceQuoteOperation<ShellFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.Shell,
source,
fillData: { poolAddress },
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromShell,
@@ -758,9 +836,10 @@ export class SamplerOperations {
makerToken: string,
takerToken: string,
makerFillAmounts: BigNumber[],
source: ERC20BridgeSource = ERC20BridgeSource.Shell,
): SourceQuoteOperation {
return new SamplerContractOperation({
source: ERC20BridgeSource.Shell,
source,
fillData: { poolAddress },
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromShell,
@@ -1022,6 +1101,8 @@ export class SamplerOperations {
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1046,6 +1127,7 @@ export class SamplerOperations {
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Belt:
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveSellQuotes(
pool,
@@ -1055,13 +1137,33 @@ export class SamplerOperations {
source,
),
);
case ERC20BridgeSource.Smoothy:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getSmoothySellQuotes(
pool,
pool.tokens.indexOf(takerToken),
pool.tokens.indexOf(makerToken),
takerFillAmounts,
),
);
case ERC20BridgeSource.Shell:
case ERC20BridgeSource.Component:
return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getShellSellQuotes(pool, makerToken, takerToken, takerFillAmounts, source),
);
case ERC20BridgeSource.LiquidityProvider:
return getLiquidityProvidersForPair(
this.liquidityProviderRegistry,
takerToken,
makerToken,
).map(pool =>
this.getLiquidityProviderSellQuotes(pool, makerToken, takerToken, takerFillAmounts),
).map(({ providerAddress, gasCost }) =>
this.getLiquidityProviderSellQuotes(
providerAddress,
makerToken,
takerToken,
takerFillAmounts,
gasCost,
),
);
case ERC20BridgeSource.MStable:
return isValidAddress(MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId])
@@ -1104,10 +1206,6 @@ export class SamplerOperations {
ERC20BridgeSource.Cream,
),
);
case ERC20BridgeSource.Shell:
return getShellsForPair(this.chainId, takerToken, makerToken).map(pool =>
this.getShellSellQuotes(pool, makerToken, takerToken, takerFillAmounts),
);
case ERC20BridgeSource.Dodo:
if (!isValidAddress(DODO_CONFIG_BY_CHAIN_ID[this.chainId].registry)) {
return [];
@@ -1151,7 +1249,7 @@ export class SamplerOperations {
return [
[takerToken, makerToken],
...getIntermediateTokens(makerToken, takerToken, {
default: [TOKENS.LINK, TOKENS.WETH],
default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH],
}).map(t => [takerToken, t, makerToken]),
].map(path =>
this.getUniswapV2SellQuotes(
@@ -1213,6 +1311,8 @@ export class SamplerOperations {
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1237,6 +1337,7 @@ export class SamplerOperations {
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Belt:
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveBuyQuotes(
pool,
@@ -1246,13 +1347,33 @@ export class SamplerOperations {
source,
),
);
case ERC20BridgeSource.Smoothy:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getSmoothyBuyQuotes(
pool,
pool.tokens.indexOf(takerToken),
pool.tokens.indexOf(makerToken),
makerFillAmounts,
),
);
case ERC20BridgeSource.Shell:
case ERC20BridgeSource.Component:
return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getShellBuyQuotes(pool, makerToken, takerToken, makerFillAmounts, source),
);
case ERC20BridgeSource.LiquidityProvider:
return getLiquidityProvidersForPair(
this.liquidityProviderRegistry,
takerToken,
makerToken,
).map(pool =>
this.getLiquidityProviderBuyQuotes(pool, makerToken, takerToken, makerFillAmounts),
).map(({ providerAddress, gasCost }) =>
this.getLiquidityProviderBuyQuotes(
providerAddress,
makerToken,
takerToken,
makerFillAmounts,
gasCost,
),
);
case ERC20BridgeSource.MStable:
return isValidAddress(MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId])
@@ -1295,10 +1416,6 @@ export class SamplerOperations {
ERC20BridgeSource.Cream,
),
);
case ERC20BridgeSource.Shell:
return getShellsForPair(this.chainId, takerToken, makerToken).map(pool =>
this.getShellBuyQuotes(pool, makerToken, takerToken, makerFillAmounts),
);
case ERC20BridgeSource.Dodo:
if (!isValidAddress(DODO_CONFIG_BY_CHAIN_ID[this.chainId].registry)) {
return [];
@@ -1337,7 +1454,7 @@ export class SamplerOperations {
[takerToken, makerToken],
// LINK is the base asset in many of the pools on Linkswap
...getIntermediateTokens(makerToken, takerToken, {
default: [TOKENS.LINK, TOKENS.WETH],
default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH],
}).map(t => [takerToken, t, makerToken]),
].map(path =>
this.getUniswapV2BuyQuotes(

View File

@@ -59,12 +59,17 @@ export enum ERC20BridgeSource {
DodoV2 = 'DODO_V2',
CryptoCom = 'CryptoCom',
Linkswap = 'Linkswap',
// Other
KyberDmm = 'KyberDMM',
Smoothy = 'Smoothy',
Component = 'Component',
Saddle = 'Saddle',
// BSC only
PancakeSwap = 'PancakeSwap',
BakerySwap = 'BakerySwap',
Nerve = 'Nerve',
Belt = 'Belt',
Ellipsis = 'Ellipsis',
PancakeSwapV2 = 'PancakeSwap_V2',
}
// tslint:disable: enum-naming
@@ -79,9 +84,12 @@ export enum CurveFunctionSelectors {
get_dx_underlying = '0x0e71d1b9',
get_dy = '0x5e0d443f',
get_dx = '0x67df02ca',
// Nerve BSC
swap = '0x91695586',
calculateSwap = '0xa95b089f',
// Smoothy
swap_uint256 = '0x5673b02d', // swap(uint256,uint256,uint256,uint256)
get_swap_amount = '0x45cf2ef6', // getSwapAmount(uint256,uint256,uint256)
// Nerve BSC, Saddle Mainnet
swap = '0x91695586', // swap(uint8,uint8,uint256,uint256,uint256)
calculateSwap = '0xa95b089f', // calculateSwap(uint8,uint8,uint256)
}
// tslint:enable: enum-naming
@@ -95,6 +103,7 @@ export interface CurveInfo {
poolAddress: string;
tokens: string[];
metaToken: string | undefined;
gasSchedule: number;
}
/**
@@ -439,7 +448,7 @@ export interface TokenAdjacencyGraph {
export interface LiquidityProviderRegistry {
[address: string]: {
tokens: string[];
gasCost: number;
gasCost: number | ((takerToken: string, makerToken: string) => number);
};
}

View File

@@ -83,7 +83,7 @@ export class QuoteRequestor {
sellTokenAddress: string, // taker token
assetFillAmount: BigNumber,
comparisonPrice?: BigNumber,
isLastLook: boolean = false,
isLastLook?: boolean | undefined,
): TakerRequestQueryParams {
const { buyAmountBaseUnits, sellAmountBaseUnits } =
marketOperation === MarketOperation.Buy
@@ -111,9 +111,11 @@ export class QuoteRequestor {
buyTokenAddress,
sellTokenAddress,
comparisonPrice: comparisonPrice === undefined ? undefined : comparisonPrice.toString(),
isLastLook: isLastLook.toString(),
protocolVersion: '4',
};
if (isLastLook) {
requestParamsWithBigNumbers.isLastLook = isLastLook.toString();
}
// convert BigNumbers to strings
// so they are digestible by axios

Some files were not shown because too many files have changed in this diff Show More