aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/0x.js')
-rw-r--r--packages/0x.js/CHANGELOG.json424
-rw-r--r--packages/0x.js/CHANGELOG.md212
-rw-r--r--packages/0x.js/README.md58
-rw-r--r--packages/0x.js/package.json103
-rw-r--r--packages/0x.js/src/0x.ts379
-rw-r--r--packages/0x.js/src/artifacts.ts19
-rw-r--r--packages/0x.js/src/artifacts/DummyToken.json22
-rw-r--r--packages/0x.js/src/artifacts/EtherToken.json287
-rw-r--r--packages/0x.js/src/artifacts/Exchange.json610
-rw-r--r--packages/0x.js/src/artifacts/Token.json172
-rw-r--r--packages/0x.js/src/artifacts/TokenRegistry.json547
-rw-r--r--packages/0x.js/src/artifacts/TokenTransferProxy.json187
-rw-r--r--packages/0x.js/src/artifacts/ZRX.json20
-rw-r--r--packages/0x.js/src/artifacts/ZRXToken.json10031
-rw-r--r--packages/0x.js/src/contract_wrappers/contract_wrapper.ts204
-rw-r--r--packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts199
-rw-r--r--packages/0x.js/src/contract_wrappers/exchange_wrapper.ts934
-rw-r--r--packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts128
-rw-r--r--packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts70
-rw-r--r--packages/0x.js/src/contract_wrappers/token_wrapper.ts434
-rw-r--r--packages/0x.js/src/globals.d.ts44
-rw-r--r--packages/0x.js/src/globalsAugment.d.ts23
-rw-r--r--packages/0x.js/src/index.ts93
-rw-r--r--packages/0x.js/src/order_watcher/event_watcher.ts99
-rw-r--r--packages/0x.js/src/order_watcher/expiration_watcher.ts75
-rw-r--r--packages/0x.js/src/order_watcher/order_state_watcher.ts384
-rw-r--r--packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts95
-rw-r--r--packages/0x.js/src/schemas/zero_ex_private_network_config_schema.ts8
-rw-r--r--packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts20
-rw-r--r--packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts86
-rw-r--r--packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts61
-rw-r--r--packages/0x.js/src/types.ts279
-rw-r--r--packages/0x.js/src/utils/assert.ts35
-rw-r--r--packages/0x.js/src/utils/constants.ts8
-rw-r--r--packages/0x.js/src/utils/decorators.ts91
-rw-r--r--packages/0x.js/src/utils/exchange_transfer_simulator.ts107
-rw-r--r--packages/0x.js/src/utils/filter_utils.ts95
-rw-r--r--packages/0x.js/src/utils/order_state_utils.ts138
-rw-r--r--packages/0x.js/src/utils/order_validation_utils.ts217
-rw-r--r--packages/0x.js/src/utils/signature_utils.ts45
-rw-r--r--packages/0x.js/src/utils/utils.ts63
-rw-r--r--packages/0x.js/test/0x.js_test.ts235
-rw-r--r--packages/0x.js/test/artifacts_test.ts55
-rw-r--r--packages/0x.js/test/assert_test.ts43
-rw-r--r--packages/0x.js/test/ether_token_wrapper_test.ts387
-rw-r--r--packages/0x.js/test/event_watcher_test.ts127
-rw-r--r--packages/0x.js/test/exchange_transfer_simulator_test.ts117
-rw-r--r--packages/0x.js/test/exchange_wrapper_test.ts1159
-rw-r--r--packages/0x.js/test/expiration_watcher_test.ts157
-rw-r--r--packages/0x.js/test/global_hooks.ts17
-rw-r--r--packages/0x.js/test/order_state_watcher_test.ts559
-rw-r--r--packages/0x.js/test/order_validation_test.ts473
-rw-r--r--packages/0x.js/test/remaining_fillable_calculator_test.ts234
-rw-r--r--packages/0x.js/test/subscription_test.ts83
-rw-r--r--packages/0x.js/test/token_registry_wrapper_test.ts128
-rw-r--r--packages/0x.js/test/token_transfer_proxy_wrapper_test.ts36
-rw-r--r--packages/0x.js/test/token_wrapper_test.ts517
-rw-r--r--packages/0x.js/test/utils/chai_setup.ts2
-rw-r--r--packages/0x.js/test/utils/fill_scenarios.ts198
-rw-r--r--packages/0x.js/test/utils/order_factory.ts46
-rw-r--r--packages/0x.js/test/utils/report_callback_errors.ts66
-rw-r--r--packages/0x.js/test/utils/token_utils.ts38
-rw-r--r--packages/0x.js/test/utils/web3_wrapper.ts14
-rw-r--r--packages/0x.js/tsconfig.json10
64 files changed, 10913 insertions, 10894 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json
index 9a750a169..e96fda9af 100644
--- a/packages/0x.js/CHANGELOG.json
+++ b/packages/0x.js/CHANGELOG.json
@@ -1,5 +1,261 @@
[
{
+ "version": "1.0.1-rc.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ },
+ {
+ "pr": 914,
+ "note": "Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts"
+ }
+ ],
+ "timestamp": 1534210131
+ },
+ {
+ "version": "1.0.1-rc.2",
+ "changes": [
+ {
+ "note": "Fixed bug caused by importing non-existent dep"
+ }
+ ],
+ "timestamp": 1532619515
+ },
+ {
+ "version": "1.0.1-rc.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1532605697
+ },
+ {
+ "timestamp": 1532357734,
+ "version": "1.0.0",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1532043100,
+ "version": "1.0.0-rc.2",
+ "changes": [
+ {
+ "note": "Remove `zeroEx.assetData` and instead re-export it's static functions directly off `ZeroEx`"
+ }
+ ]
+ },
+ {
+ "timestamp": 1532043000,
+ "version": "1.0.0-rc.1",
+ "changes": [
+ {
+ "note": "Remove tokenRegistry wrapper",
+ "pr": 863
+ },
+ {
+ "note": "Rename `zeroEx.token` to `zeroEx.erc20Token`, and add `zeroEx.erc721Token`",
+ "pr": 863
+ },
+ {
+ "note": "Rename `zeroEx.proxy` to `zeroEx.erc20Proxy` and add `zeroEx.erc721Proxy`",
+ "pr": 863
+ },
+ {
+ "note":
+ "Refactored `ZeroEx.isValidSignature` to `zeroEx.isValidSignatureAsync`. It is now async so that it can verify contract-dependent signature types",
+ "pr": 863
+ },
+ {
+ "note":
+ "Refactored `signOrderHashAsync` to `ecSignOrderHashAsync`. There are now many non-ECSignature ways to sign orders too.",
+ "pr": 863
+ },
+ {
+ "note":
+ "Removed `createOrderWatcherAsync` method. Will be added back once OrderWatcher is refactored for V2",
+ "pr": 863
+ },
+ {
+ "note": "0x.js exports renamed contract events and event arg types",
+ "pr": 863
+ },
+ {
+ "note": "Export `ZeroEx.assetData` with methods to decode/encode assetData fields found in 0x orders",
+ "pr": 884
+ }
+ ]
+ },
+ {
+ "timestamp": 1531919263,
+ "version": "0.38.6",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1531149657,
+ "version": "0.38.5",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1529397769,
+ "version": "0.38.4",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1527617805,
+ "version": "0.38.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1527617227,
+ "version": "0.38.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1527616612,
+ "version": "0.38.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "version": "0.38.0",
+ "changes": [
+ {
+ "note": "Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async",
+ "pr": 579
+ },
+ {
+ "note":
+ "Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage",
+ "pr": 579
+ }
+ ],
+ "timestamp": 1527008270
+ },
+ {
+ "timestamp": 1525477860,
+ "version": "0.37.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "timestamp": 1525453812,
+ "version": "0.37.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "version": "0.37.0",
+ "changes": [
+ {
+ "note": "Fixed expiration watcher comparator to handle orders with equal expiration times",
+ "pr": 526
+ },
+ {
+ "note": "Update Web3 Provider Engine to 14.0.4",
+ "pr": 555
+ },
+ {
+ "note": "Add `zeroEx.getProvider()`",
+ "pr": 559
+ },
+ {
+ "note": "Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature`",
+ "pr": 559
+ }
+ ],
+ "timestamp": 1525428773
+ },
+ {
+ "version": "0.36.3",
+ "changes": [
+ {
+ "note": "Move @0xproject/migrations to devDependencies"
+ }
+ ],
+ "timestamp": 1524079658
+ },
+ {
+ "timestamp": 1524073495,
+ "version": "0.36.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "version": "0.36.1",
+ "changes": [
+ {
+ "note": "Internal changes and refactoring"
+ },
+ {
+ "note": "Fix redundant expired order removal bug",
+ "pr": 527
+ }
+ ],
+ "timestamp": 1524044013
+ },
+ {
+ "version": "0.36.0",
+ "changes": [
+ {
+ "note": "Moved Web3.Provider to `@0xproject/types:Provider`",
+ "pr": 501
+ },
+ {
+ "note":
+ "Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder",
+ "pr": 510
+ }
+ ],
+ "timestamp": 1523462196
+ },
+ {
+ "version": "0.35.0",
+ "changes": [
+ {
+ "note":
+ "Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout`",
+ "pr": 485
+ }
+ ],
+ "timestamp": 1522673609
+ },
+ {
"version": "0.34.0",
"changes": [
{
@@ -35,8 +291,7 @@
"pr": 456
}
],
- "timestamp": 1521298800,
- "isPublished": true
+ "timestamp": 1521298800
},
{
"version": "0.33.1",
@@ -45,8 +300,7 @@
"note": "Add missing EthersJs typescript typings as dependency"
}
],
- "timestamp": 1520434800,
- "isPublished": true
+ "timestamp": 1520434800
},
{
"version": "0.33.0",
@@ -72,8 +326,7 @@
"pr": 429
}
],
- "timestamp": 1520089200,
- "isPublished": true
+ "timestamp": 1520089200
},
{
"version": "0.32.2",
@@ -83,8 +336,7 @@
"pr": 389
}
],
- "timestamp": 1518102000,
- "isPublished": true
+ "timestamp": 1518102000
},
{
"version": "0.32.1",
@@ -98,8 +350,7 @@
"pr": 371
}
],
- "timestamp": 1517929200,
- "isPublished": true
+ "timestamp": 1517929200
},
{
"version": "0.32.0",
@@ -114,8 +365,7 @@
"pr": 366
}
],
- "timestamp": 1517756400,
- "isPublished": true
+ "timestamp": 1517756400
},
{
"version": "0.31.1",
@@ -125,8 +375,7 @@
"pr": 357
}
],
- "timestamp": 1517410800,
- "isPublished": true
+ "timestamp": 1517410800
},
{
"version": "0.31.0",
@@ -137,8 +386,7 @@
"pr": 349
}
],
- "timestamp": 1517238000,
- "isPublished": true
+ "timestamp": 1517238000
},
{
"version": "0.30.2",
@@ -151,8 +399,7 @@
"note": "Move @0xproject/types to dependencies from devDependencies fixing missing type errors"
}
],
- "timestamp": 1517151600,
- "isPublished": true
+ "timestamp": 1517151600
},
{
"version": "0.30.1",
@@ -166,8 +413,7 @@
"pr": 341
}
],
- "timestamp": 1516719600,
- "isPublished": true
+ "timestamp": 1516719600
},
{
"version": "0.30.0",
@@ -186,8 +432,7 @@
"pr": 321
}
],
- "timestamp": 1516114800,
- "isPublished": true
+ "timestamp": 1516114800
},
{
"version": "0.29.1",
@@ -197,8 +442,7 @@
"pr": 305
}
],
- "timestamp": 1515596400,
- "isPublished": true
+ "timestamp": 1515596400
},
{
"version": "0.29.0",
@@ -212,8 +456,7 @@
"pr": 287
}
],
- "timestamp": 1514386800,
- "isPublished": true
+ "timestamp": 1514386800
},
{
"version": "0.28.0",
@@ -259,8 +502,7 @@
"pr": 278
}
],
- "timestamp": 1513695600,
- "isPublished": true
+ "timestamp": 1513695600
},
{
"version": "0.27.1",
@@ -269,8 +511,7 @@
"note": "Export `TransactionOpts` type"
}
],
- "timestamp": 1511794800,
- "isPublished": true
+ "timestamp": 1511794800
},
{
"version": "0.27.0",
@@ -315,8 +556,7 @@
"pr": 236
}
],
- "timestamp": 1511794800,
- "isPublished": true
+ "timestamp": 1511794800
},
{
"version": "0.26.0",
@@ -336,8 +576,7 @@
"pr": 225
}
],
- "timestamp": 1511190000,
- "isPublished": true
+ "timestamp": 1511190000
},
{
"version": "0.25.1",
@@ -356,8 +595,7 @@
"pr": 200
}
],
- "timestamp": 1510498800,
- "isPublished": true
+ "timestamp": 1510498800
},
{
"version": "0.23.0",
@@ -370,8 +608,7 @@
"note": "Subscribe callbacks now receive an error object as their first argument"
}
],
- "timestamp": 1510412400,
- "isPublished": true
+ "timestamp": 1510412400
},
{
"version": "0.22.6",
@@ -381,8 +618,7 @@
"pr": 206
}
],
- "timestamp": 1510239600,
- "isPublished": true
+ "timestamp": 1510239600
},
{
"version": "0.22.5",
@@ -391,8 +627,7 @@
"note": "Re-publish v0.22.4 to fix publishing issue"
}
],
- "timestamp": 1509980400,
- "isPublished": true
+ "timestamp": 1509980400
},
{
"version": "0.22.4",
@@ -401,8 +636,7 @@
"note": "Upgraded bignumber.js to a new version that ships with native typings"
}
],
- "timestamp": 1508857200,
- "isPublished": true
+ "timestamp": 1508857200
},
{
"version": "0.22.3",
@@ -412,8 +646,7 @@
"pr": 199
}
],
- "timestamp": 1508857200,
- "isPublished": true
+ "timestamp": 1508857200
},
{
"version": "0.22.2",
@@ -423,8 +656,7 @@
"pr": 197
}
],
- "timestamp": 1508770800,
- "isPublished": true
+ "timestamp": 1508770800
},
{
"version": "0.22.0",
@@ -439,8 +671,7 @@
"pr": 187
}
],
- "timestamp": 1508079600,
- "isPublished": true
+ "timestamp": 1508079600
},
{
"version": "0.21.4",
@@ -451,8 +682,7 @@
"pr": 194
}
],
- "timestamp": 1507820400,
- "isPublished": true
+ "timestamp": 1507820400
},
{
"version": "0.21.3",
@@ -462,8 +692,7 @@
"pr": 193
}
],
- "timestamp": 1507734000,
- "isPublished": true
+ "timestamp": 1507734000
},
{
"version": "0.21.2",
@@ -473,8 +702,7 @@
"pr": 190
}
],
- "timestamp": 1507647600,
- "isPublished": true
+ "timestamp": 1507647600
},
{
"version": "0.21.1",
@@ -484,8 +712,7 @@
"pr": 189
}
],
- "timestamp": 1507647600,
- "isPublished": true
+ "timestamp": 1507647600
},
{
"version": "0.21.0",
@@ -531,8 +758,7 @@
"pr": 185
}
],
- "timestamp": 1507561200,
- "isPublished": true
+ "timestamp": 1507561200
},
{
"version": "0.20.0",
@@ -550,8 +776,7 @@
"pr": 181
}
],
- "timestamp": 1507129200,
- "isPublished": true
+ "timestamp": 1507129200
},
{
"version": "0.19.0",
@@ -569,8 +794,7 @@
"pr": 175
}
],
- "timestamp": 1506610800,
- "isPublished": true
+ "timestamp": 1506610800
},
{
"version": "0.18.0",
@@ -580,8 +804,7 @@
"pr": 170
}
],
- "timestamp": 1506351600,
- "isPublished": true
+ "timestamp": 1506351600
},
{
"version": "0.17.0",
@@ -591,8 +814,7 @@
"pr": 171
}
],
- "timestamp": 1506351600,
- "isPublished": true
+ "timestamp": 1506351600
},
{
"version": "0.16.0",
@@ -615,8 +837,7 @@
"pr": 165
}
],
- "timestamp": 1505833200,
- "isPublished": true
+ "timestamp": 1505833200
},
{
"version": "0.15.0",
@@ -627,8 +848,7 @@
"pr": 161
}
],
- "timestamp": 1504796400,
- "isPublished": true
+ "timestamp": 1504796400
},
{
"version": "0.14.2",
@@ -638,8 +858,7 @@
"pr": 160
}
],
- "timestamp": 1504710000,
- "isPublished": true
+ "timestamp": 1504710000
},
{
"version": "0.14.1",
@@ -649,8 +868,7 @@
"pr": 159
}
],
- "timestamp": 1504710000,
- "isPublished": true
+ "timestamp": 1504710000
},
{
"version": "0.14.0",
@@ -668,8 +886,7 @@
"pr": 157
}
],
- "timestamp": 1504623600,
- "isPublished": true
+ "timestamp": 1504623600
},
{
"version": "0.13.0",
@@ -693,8 +910,7 @@
"pr": 152
}
],
- "timestamp": 1504623600,
- "isPublished": true
+ "timestamp": 1504623600
},
{
"version": "0.12.1",
@@ -712,8 +928,7 @@
"pr": 139
}
],
- "timestamp": 1504278000,
- "isPublished": true
+ "timestamp": 1504278000
},
{
"version": "0.11.0",
@@ -731,8 +946,7 @@
"pr": 137
}
],
- "timestamp": 1503500400,
- "isPublished": true
+ "timestamp": 1503500400
},
{
"version": "0.10.4",
@@ -742,8 +956,7 @@
"pr": 135
}
],
- "timestamp": 1503500400,
- "isPublished": true
+ "timestamp": 1503500400
},
{
"version": "0.10.1",
@@ -797,8 +1010,7 @@
"pr": 127
}
],
- "timestamp": 1503500400,
- "isPublished": true
+ "timestamp": 1503500400
},
{
"version": "0.9.3",
@@ -808,8 +1020,7 @@
"pr": 118
}
],
- "timestamp": 1503327600,
- "isPublished": true
+ "timestamp": 1503327600
},
{
"version": "0.9.2",
@@ -822,8 +1033,7 @@
"pr": 118
}
],
- "timestamp": 1503241200,
- "isPublished": true
+ "timestamp": 1503241200
},
{
"version": "0.9.1",
@@ -833,8 +1043,7 @@
"pr": 120
}
],
- "timestamp": 1502809200,
- "isPublished": true
+ "timestamp": 1502809200
},
{
"version": "0.9.0",
@@ -871,8 +1080,7 @@
"pr": 109
}
],
- "timestamp": 1500994800,
- "isPublished": true
+ "timestamp": 1500994800
},
{
"version": "0.8.0",
@@ -914,8 +1122,7 @@
"note": "Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance"
}
],
- "timestamp": 1499094000,
- "isPublished": true
+ "timestamp": 1499094000
},
{
"version": "0.7.1",
@@ -926,8 +1133,7 @@
"pr": 81
}
],
- "timestamp": 1498402800,
- "isPublished": true
+ "timestamp": 1498402800
},
{
"version": "0.7.0",
@@ -949,8 +1155,7 @@
"Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`"
}
],
- "timestamp": 1498057200,
- "isPublished": true
+ "timestamp": 1498057200
},
{
"version": "0.6.2",
@@ -962,8 +1167,7 @@
"note": "Improved documentation"
}
],
- "timestamp": 1497970800,
- "isPublished": true
+ "timestamp": 1497970800
},
{
"version": "0.6.1",
@@ -972,8 +1176,7 @@
"note": "Improved documentation"
}
],
- "timestamp": 1497798000,
- "isPublished": true
+ "timestamp": 1497798000
},
{
"version": "0.6.0",
@@ -985,8 +1188,7 @@
"note": "Added types for contract event arguments"
}
],
- "timestamp": 1497798000,
- "isPublished": true
+ "timestamp": 1497798000
},
{
"version": "0.5.2",
@@ -996,8 +1198,7 @@
"Fixed the bug in `postpublish` script that caused that only unminified UMD bundle was uploaded to release page"
}
],
- "timestamp": 1497452400,
- "isPublished": true
+ "timestamp": 1497452400
},
{
"version": "0.5.1",
@@ -1006,7 +1207,6 @@
"note": "Added `postpublish` script to publish to Github Releases with assets."
}
],
- "timestamp": 1497452400,
- "isPublished": true
+ "timestamp": 1497452400
}
]
diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md
index e8c2e6473..adeaed9eb 100644
--- a/packages/0x.js/CHANGELOG.md
+++ b/packages/0x.js/CHANGELOG.md
@@ -1,10 +1,108 @@
<!--
-This file is auto-generated using the monorepo-scripts package. Don't edit directly.
+changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
+## v1.0.1-rc.3 - _August 13, 2018_
+
+ * Dependencies updated
+ * Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts (#914)
+
+## v1.0.1-rc.2 - _July 26, 2018_
+
+ * Fixed bug caused by importing non-existent dep
+
+## v1.0.1-rc.1 - _July 26, 2018_
+
+ * Dependencies updated
+
+## v1.0.0 - _July 23, 2018_
+
+ * Dependencies updated
+
+## v1.0.0-rc.2 - _July 19, 2018_
+
+ * Remove `zeroEx.assetData` and instead re-export it's static functions directly off `ZeroEx`
+
+## v1.0.0-rc.1 - _July 19, 2018_
+
+ * Remove tokenRegistry wrapper (#863)
+ * Rename `zeroEx.token` to `zeroEx.erc20Token`, and add `zeroEx.erc721Token` (#863)
+ * Rename `zeroEx.proxy` to `zeroEx.erc20Proxy` and add `zeroEx.erc721Proxy` (#863)
+ * Refactored `ZeroEx.isValidSignature` to `zeroEx.isValidSignatureAsync`. It is now async so that it can verify contract-dependent signature types (#863)
+ * Refactored `signOrderHashAsync` to `ecSignOrderHashAsync`. There are now many non-ECSignature ways to sign orders too. (#863)
+ * Removed `createOrderWatcherAsync` method. Will be added back once OrderWatcher is refactored for V2 (#863)
+ * 0x.js exports renamed contract events and event arg types (#863)
+ * Export `ZeroEx.assetData` with methods to decode/encode assetData fields found in 0x orders (#884)
+
+## v0.38.6 - _July 18, 2018_
+
+ * Dependencies updated
+
+## v0.38.5 - _July 9, 2018_
+
+ * Dependencies updated
+
+## v0.38.4 - _June 19, 2018_
+
+ * Dependencies updated
+
+## v0.38.3 - _May 29, 2018_
+
+ * Dependencies updated
+
+## v0.38.2 - _May 29, 2018_
+
+ * Dependencies updated
+
+## v0.38.1 - _May 29, 2018_
+
+ * Dependencies updated
+
+## v0.38.0 - _May 22, 2018_
+
+ * Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async (#579)
+ * Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage (#579)
+
+## v0.37.2 - _May 4, 2018_
+
+ * Dependencies updated
+
+## v0.37.1 - _May 4, 2018_
+
+ * Dependencies updated
+
+## v0.37.0 - _May 4, 2018_
+
+ * Fixed expiration watcher comparator to handle orders with equal expiration times (#526)
+ * Update Web3 Provider Engine to 14.0.4 (#555)
+ * Add `zeroEx.getProvider()` (#559)
+ * Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature` (#559)
+
+## v0.36.3 - _April 18, 2018_
+
+ * Move @0xproject/migrations to devDependencies
+
+## v0.36.2 - _April 18, 2018_
+
+ * Dependencies updated
+
+## v0.36.1 - _April 18, 2018_
+
+ * Internal changes and refactoring
+ * Fix redundant expired order removal bug (#527)
+
+## v0.36.0 - _April 11, 2018_
+
+ * Moved Web3.Provider to `@0xproject/types:Provider` (#501)
+ * Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder (#510)
+
+## v0.35.0 - _April 2, 2018_
+
+ * Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout` (#485)
+
## v0.34.0 - _April 2, 2018_
* Fix the bug causing `zeroEx.exchange.fillOrdersUpToAsync` validation to fail if there were some extra orders passed (#470)
@@ -12,16 +110,16 @@ CHANGELOG
* Add `zeroEx.createOrderStateWatcher` to allow creating arbitrary number of OrderStateWatchers (#488)
* Added `stateLayer` setting to `OrderStateWatcherConfig` so OrderStateWatcher can be set to monitor different blockchain state layers (#488)
-## v0.33.2 - _March 18, 2018_
+## v0.33.2 - _March 17, 2018_
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
* Consolidate `Order`, `SignedOrder`, and `ECSignature` into the `@0xproject/types` package (#456)
-## v0.33.1 - _March 8, 2018_
+## v0.33.1 - _March 7, 2018_
* Add missing EthersJs typescript typings as dependency
-## v0.33.0 - _March 4, 2018_
+## v0.33.0 - _March 3, 2018_
* Validate and lowercase all addresses in public methods (#373)
* Improve validation to force passing contract addresses on private networks (#385)
@@ -29,54 +127,54 @@ CHANGELOG
* Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
* Move web3 typings from devDep to dep since cannot use this package without it (#429)
-## v0.32.2 - _February 9, 2018_
+## v0.32.2 - _February 8, 2018_
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
-## v0.32.1 - _February 7, 2018_
+## v0.32.1 - _February 6, 2018_
* Reorganized `BlockParamLiteral` export into `@0xproject/types` package (#355)
* Now using `abi-gen` package to generate ContractEventArgs types (#371)
-## v0.32.0 - _February 5, 2018_
+## v0.32.0 - _February 4, 2018_
* Add `zeroEx.etherToken.getContractAddressIfExists` (#350)
* Fixed the bug causing order watcher to throw if there is an event with the same signature but different indexed fields (#366)
-## v0.31.1 - _February 1, 2018_
+## v0.31.1 - _January 31, 2018_
* Fix the bug causing order watcher to throw if makerToken === zrx (#357)
-## v0.31.0 - _January 30, 2018_
+## v0.31.0 - _January 29, 2018_
* Add the `shouldAddPersonalMessagePrefix` parameter to `signOrderHashAsync` so that the caller can decide on whether to add the personalMessage prefix before relaying the request to the signer. Parity Signer, Ledger and TestRPC add the prefix themselves, Metamask expects it to have already been added. (#349)
-## v0.30.2 - _January 29, 2018_
+## v0.30.2 - _January 28, 2018_
* Add Rinkeby testnet addresses to artifacts (#337)
* Move @0xproject/types to dependencies from devDependencies fixing missing type errors
-## v0.30.1 - _January 24, 2018_
+## v0.30.1 - _January 23, 2018_
* Fix a bug allowing negative fill values (#212)
* Fix a bug that made it impossible to pass a custom ZRX address (#341)
-## v0.30.0 - _January 17, 2018_
+## v0.30.0 - _January 16, 2018_
* Add an error parameter to the order watcher callback (#312)
* Fix a bug making it impossible to catch some errors from awaitTransactionMinedAsync (#312)
* Fix a bug in fillOrdersUpTo validation making it impossible to fill up to if user doesn't have enough balance to fully fill all the orders (#321)
-## v0.29.1 - _January 11, 2018_
+## v0.29.1 - _January 10, 2018_
* Fixed bignumber config issue #301 (#305)
-## v0.29.0 - _December 28, 2017_
+## v0.29.0 - _December 27, 2017_
* Assert baseUnit amount supplied to `toUnitAmount` is integer amount. (#287)
* `toBaseUnitAmount` throws if amount supplied has too many decimals (#287)
-## v0.28.0 - _December 20, 2017_
+## v0.28.0 - _December 19, 2017_
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
@@ -88,11 +186,11 @@ CHANGELOG
* Support `Deposit` and `Withdraw` events on etherToken (#277)
* Improve the error message when taker is not a string (#278)
-## v0.27.1 - _November 28, 2017_
+## v0.27.1 - _November 27, 2017_
* Export `TransactionOpts` type
-## v0.27.0 - _November 28, 2017_
+## v0.27.0 - _November 27, 2017_
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
* Add a required property `networkId` to `ZeroExConfig` (#233)
@@ -104,65 +202,65 @@ CHANGELOG
* All transaction sending methods now call `estimateGas` if no gas amount was supplied (#235)
* Modify order validation methods to validate against the `latest` block, not against the `pending` block (#236)
-## v0.26.0 - _November 21, 2017_
+## v0.26.0 - _November 20, 2017_
* Add post-formatter for logs converting `blockNumber`, `logIndex`, `transactionIndex` from hexes to numbers (#231)
* Remove support for Async callback types when used in Subscribe functions (#222)
* In OrderWatcher subscribe to ZRX Token Transfer and Approval events when maker token is different (#225)
-## v0.25.1 - _November 13, 2017_
+## v0.25.1 - _November 12, 2017_
* Standardise on Cancelled over Canceled (#217)
* Add missing `DecodedLogEvent` type to exported types (#205)
* Normalized the transactionReceipt status to be `null|0|1`, 1 meaning transaction execution successful, 0 unsuccessful and `null` if it is a pre-byzantinium transaction. (#200)
-## v0.23.0 - _November 12, 2017_
+## v0.23.0 - _November 11, 2017_
* Fixed unhandled promise rejection error in subscribe methods (#209)
* Subscribe callbacks now receive an error object as their first argument
-## v0.22.6 - _November 10, 2017_
+## v0.22.6 - _November 9, 2017_
* Add a timeout parameter to transaction awaiting (#206)
-## v0.22.5 - _November 7, 2017_
+## v0.22.5 - _November 6, 2017_
* Re-publish v0.22.4 to fix publishing issue
-## v0.22.4 - _October 25, 2017_
+## v0.22.4 - _October 24, 2017_
* Upgraded bignumber.js to a new version that ships with native typings
-## v0.22.3 - _October 25, 2017_
+## v0.22.3 - _October 24, 2017_
* Fixed an issue with new version of testrpc and unlimited proxy allowance (#199)
-## v0.22.2 - _October 24, 2017_
+## v0.22.2 - _October 23, 2017_
* Fixed rounding of maker fill amount and incorrect validation of partial fees (#197)
-## v0.22.0 - _October 16, 2017_
+## v0.22.0 - _October 15, 2017_
* Started using `OrderFillRequest` interface instead of `OrderFillOrKillRequest` interface for `zeroEx.exchange.batchFillOrKill` (#187)
* Removed `OrderFillOrKillRequest` (#187)
-## v0.21.4 - _October 13, 2017_
+## v0.21.4 - _October 12, 2017_
* Made 0x.js more type-safe by making `getLogsAsync` and `subscribe/subscribeAsync` generics parametrized with arg type (#194)
-## v0.21.3 - _October 12, 2017_
+## v0.21.3 - _October 11, 2017_
* Fixed a bug causing order fills to throw `INSUFFICIENT_TAKER_ALLOWANCE` (#193)
-## v0.21.2 - _October 11, 2017_
+## v0.21.2 - _October 10, 2017_
* Exported `ContractEventArg` as a public type (#190)
-## v0.21.1 - _October 11, 2017_
+## v0.21.1 - _October 10, 2017_
* Fixed a bug in subscriptions (#189)
-## v0.21.0 - _October 10, 2017_
+## v0.21.0 - _October 9, 2017_
* Complete rewrite of subscription logic (#182)
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
@@ -177,27 +275,27 @@ CHANGELOG
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
* Fixed the batch fills validation by emulating all balance & proxy allowance changes (#185)
-## v0.20.0 - _October 5, 2017_
+## v0.20.0 - _October 4, 2017_
* Add `zeroEx.token.getLogsAsync` (#178)
* Add `zeroEx.exchange.getLogsAsync` (#178)
* Fixed fees validation when one of the tokens transferred is ZRX (#181)
-## v0.19.0 - _September 29, 2017_
+## v0.19.0 - _September 28, 2017_
* Made order validation optional (#172)
* Added Ropsten testnet support (#173)
* Fixed a bug causing awaitTransactionMinedAsync to DDos backend nodes (#175)
-## v0.18.0 - _September 26, 2017_
+## v0.18.0 - _September 25, 2017_
* Added `zeroEx.exchange.validateOrderFillableOrThrowAsync` to simplify orderbook pruning (#170)
-## v0.17.0 - _September 26, 2017_
+## v0.17.0 - _September 25, 2017_
* Made `zeroEx.exchange.getZRXTokenAddressAsync` public (#171)
-## v0.16.0 - _September 20, 2017_
+## v0.16.0 - _September 19, 2017_
* Added the ability to specify custom contract addresses to be used with 0x.js (#165)
* ZeroExConfig.exchangeContractAddress
@@ -205,48 +303,48 @@ CHANGELOG
* ZeroExConfig.etherTokenContractAddress
* Added `zeroEx.tokenRegistry.getContractAddressAsync` (#165)
-## v0.15.0 - _September 8, 2017_
+## v0.15.0 - _September 7, 2017_
* Added the ability to specify a historical `blockNumber` at which to query the blockchain's state when calling a token or exchange method (#161)
-## v0.14.2 - _September 7, 2017_
+## v0.14.2 - _September 6, 2017_
* Fixed an issue with bignumber.js types not found (#160)
-## v0.14.1 - _September 7, 2017_
+## v0.14.1 - _September 6, 2017_
* Fixed an issue with Artifact type not found (#159)
-## v0.14.0 - _September 6, 2017_
+## v0.14.0 - _September 5, 2017_
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#157)
-## v0.13.0 - _September 6, 2017_
+## v0.13.0 - _September 5, 2017_
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
* Added signature validation to `validateFillOrderThrowIfInvalidAsync` (#152)
-## v0.12.1 - _September 2, 2017_
+## v0.12.1 - _September 1, 2017_
* Added the support for web3@1.x.x provider (#142)
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
* Added the ability to specify `gasPrice` when instantiating `ZeroEx` (#139)
-## v0.11.0 - _August 24, 2017_
+## v0.11.0 - _August 23, 2017_
* Added `zeroEx.token.setUnlimitedProxyAllowanceAsync` (#137)
* Added `zeroEx.token.setUnlimitedAllowanceAsync` (#137)
* Added `zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS` (#137)
-## v0.10.4 - _August 24, 2017_
+## v0.10.4 - _August 23, 2017_
* Fixed a bug where checksummed addresses were being pulled from artifacts and not lower-cased. (#135)
-## v0.10.1 - _August 24, 2017_
+## v0.10.1 - _August 23, 2017_
* Added `zeroEx.exchange.validateFillOrderThrowIfInvalidAsync` (#128)
* Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128)
@@ -261,20 +359,20 @@ CHANGELOG
* Added clear error message when checksummed address is passed to a public method (#124)
* Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs (#127)
-## v0.9.3 - _August 22, 2017_
+## v0.9.3 - _August 21, 2017_
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
-## v0.9.2 - _August 21, 2017_
+## v0.9.2 - _August 20, 2017_
* *This version was unpublished because of a publishing issue.*
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
-## v0.9.1 - _August 16, 2017_
+## v0.9.1 - _August 15, 2017_
* Fixed the bug causing `zeroEx.token.getBalanceAsync()` to fail if no addresses available (#120)
-## v0.9.0 - _July 26, 2017_
+## v0.9.0 - _July 25, 2017_
* Migrated to the new version of smart contracts (#101)
* Removed the ability to call methods on multiple authorized Exchange smart contracts (#106)
@@ -285,7 +383,7 @@ CHANGELOG
* Updated to typescript v2.4 (#104)
* Fixed an issue with incorrect balance/allowance validation when ZRX is one of the tokens traded (#109)
-## v0.8.0 - _July 4, 2017_
+## v0.8.0 - _July 3, 2017_
* Added the ability to call methods on different authorized versions of the Exchange smart contract (#82)
* Updated contract artifacts to reflect latest changes to the smart contracts (0xproject/contracts#59)
@@ -298,35 +396,35 @@ CHANGELOG
* `zeroEx.tokenRegistry.invalidateContractInstance`
* Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance
-## v0.7.1 - _June 26, 2017_
+## v0.7.1 - _June 25, 2017_
* Added the ability to convert Ether to wrapped Ether tokens and back via `zeroEx.etherToken.depostAsync` and `zeroEx.etherToken.withdrawAsync` (#81)
-## v0.7.0 - _June 22, 2017_
+## v0.7.0 - _June 21, 2017_
* Added Kovan smart contract artifacts (#78)
* Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync` (#72)
* Started returning cancelledAmount from `cancelOrderAsync` (#72)
* Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`
-## v0.6.2 - _June 21, 2017_
+## v0.6.2 - _June 20, 2017_
* Reduced bundle size
* Improved documentation
-## v0.6.1 - _June 19, 2017_
+## v0.6.1 - _June 18, 2017_
* Improved documentation
-## v0.6.0 - _June 19, 2017_
+## v0.6.0 - _June 18, 2017_
* Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance
* Added types for contract event arguments
-## v0.5.2 - _June 15, 2017_
+## v0.5.2 - _June 14, 2017_
* Fixed the bug in `postpublish` script that caused that only unminified UMD bundle was uploaded to release page
-## v0.5.1 - _June 15, 2017_
+## v0.5.1 - _June 14, 2017_
* Added `postpublish` script to publish to Github Releases with assets.
diff --git a/packages/0x.js/README.md b/packages/0x.js/README.md
index 5b17dac8b..fd6217151 100644
--- a/packages/0x.js/README.md
+++ b/packages/0x.js/README.md
@@ -1,5 +1,9 @@
## 0x.js
+A TypeScript/Javascript library for interacting with the 0x protocol.
+
+### Read the [Documentation](https://0xproject.com/docs/0x.js).
+
## Installation
0x.js ships as both a [UMD](https://github.com/umdjs/umd) module and a [CommonJS](https://en.wikipedia.org/wiki/CommonJS) package.
@@ -38,10 +42,54 @@ Download the UMD module from our [releases page](https://github.com/0xProject/0x
<script type="text/javascript" src="0x.js"></script>
```
-## Documentation
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of 0x protocol. To report bugs within this package, please create an issue in this repository.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
+
+### Install dependencies
+
+If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
+
+```bash
+yarn config set workspaces-experimental true
+```
+
+Then install dependencies
+
+```bash
+yarn install
+```
+
+### Build
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=0x.js yarn build
+```
+
+Or continuously rebuild on change:
+
+```bash
+PKG=0x.js yarn watch
+```
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
-Extensive documentation of 0x.js can be found on [our website][docs-url].
+### Run Tests
-[website-url]: https://0xproject.com/
-[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
-[docs-url]: https://0xproject.com/docs/0xjs
+```bash
+yarn test
+```
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json
index b27eb188b..cf7b1962f 100644
--- a/packages/0x.js/package.json
+++ b/packages/0x.js/package.json
@@ -1,6 +1,9 @@
{
"name": "0x.js",
- "version": "0.34.0",
+ "version": "1.0.1-rc.3",
+ "engines": {
+ "node": ">=6.12"
+ },
"description": "A javascript library for interacting with the 0x protocol",
"keywords": [
"0x.js",
@@ -12,28 +15,30 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
- "build:watch": "tsc -w",
- "prebuild": "run-s clean generate_contract_wrappers",
- "build": "run-p build:umd:prod build:commonjs; exit 0;",
- "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
- "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
+ "watch_without_deps": "yarn pre_build && tsc -w",
+ "build": "yarn pre_build && yarn build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
+ "build:all": "run-p build:umd:prod build:commonjs; exit 0;",
+ "pre_build": "run-s update_artifacts generate_contract_wrappers",
+ "copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
+ "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
+ "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(ZRXToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
+ "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"test:circleci": "run-s test:coverage",
- "test": "run-s clean test:commonjs",
+ "test": "yarn run_mocha",
+ "rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;",
- "clean": "shx rm -rf _bundles lib test_temp scripts",
+ "clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"build:umd:prod": "NODE_ENV=production webpack",
- "build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
- "test:commonjs": "run-s build:commonjs run_mocha",
- "run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit",
+ "build:commonjs": "tsc && yarn copy_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
+ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
- "docs:stage": "yarn build && node ./scripts/stage_docs.js",
+ "docs:stage": "node scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
},
"config": {
- "artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken",
+ "contracts": "ZRXToken",
"postpublish": {
"assets": [
"packages/0x.js/_bundles/index.js",
@@ -42,9 +47,15 @@
"docPublishConfigs": {
"extraFileIncludes": [
"../types/src/index.ts",
- "./src/contract_wrappers/generated/ether_token.ts",
- "./src/contract_wrappers/generated/token.ts",
- "./src/contract_wrappers/generated/exchange.ts"
+ "../ethereum-types/src/index.ts",
+ "../contract-wrappers/src/types.ts",
+ "../contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts",
+ "../contract-wrappers/src/contract_wrappers/exchange_wrapper.ts",
+ "../contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts",
+ "../contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts",
+ "../contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts",
+ "../contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts",
+ "../order-watcher/src/order_watcher/order_watcher.ts"
],
"s3BucketPath": "s3://doc-jsons/0x.js/",
"s3StagingBucketPath": "s3://staging-doc-jsons/0x.js/"
@@ -56,21 +67,16 @@
"url": "https://github.com/0xProject/0x-monorepo"
},
"license": "Apache-2.0",
- "engines": {
- "node": ">=6.0.0"
- },
"devDependencies": {
- "@0xproject/abi-gen": "^0.2.8",
- "@0xproject/dev-utils": "^0.3.3",
- "@0xproject/monorepo-scripts": "^0.1.15",
- "@0xproject/tslint-config": "^0.4.13",
- "@types/bintrees": "^1.0.2",
- "@types/jsonschema": "^1.1.1",
+ "@0xproject/abi-gen": "^1.0.5",
+ "@0xproject/dev-utils": "^1.0.4",
+ "@0xproject/migrations": "^1.0.4",
+ "@0xproject/monorepo-scripts": "^1.0.5",
+ "@0xproject/tslint-config": "^1.0.5",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
"@types/sinon": "^2.2.2",
- "@types/uuid": "^3.4.2",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -78,42 +84,33 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
- "mocha": "^4.0.1",
+ "make-promises-safe": "^1.1.0",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
- "prettier": "^1.11.1",
- "request": "^2.81.0",
- "request-promise-native": "^1.0.5",
"shx": "^0.2.2",
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
- "truffle-hdwallet-provider": "^0.0.3",
- "tslint": "5.8.0",
+ "tslint": "5.11.0",
"typedoc": "0xProject/typedoc",
- "types-bn": "^0.0.1",
- "typescript": "2.7.1",
- "web3-provider-engine": "^13.0.1",
+ "typescript": "2.9.2",
"webpack": "^3.1.0"
},
"dependencies": {
- "@0xproject/assert": "^0.2.4",
- "@0xproject/base-contract": "^0.0.6",
- "@0xproject/json-schemas": "^0.7.18",
- "@0xproject/types": "^0.4.2",
- "@0xproject/typescript-typings": "^0.0.2",
- "@0xproject/utils": "^0.4.4",
- "@0xproject/web3-wrapper": "^0.4.0",
- "bintrees": "^1.0.2",
- "bn.js": "^4.11.8",
- "ethereumjs-abi": "^0.6.4",
- "ethereumjs-blockstream": "^2.0.6",
- "ethereumjs-util": "^5.1.1",
- "ethers-contracts": "^2.2.1",
- "js-sha3": "^0.7.0",
- "lodash": "^4.17.4",
- "uuid": "^3.1.0",
- "web3": "^0.20.0"
+ "@0xproject/assert": "^1.0.5",
+ "@0xproject/base-contract": "^2.0.0-rc.1",
+ "@0xproject/contract-wrappers": "^1.0.1-rc.3",
+ "@0xproject/order-utils": "^1.0.1-rc.3",
+ "@0xproject/sol-compiler": "^1.0.5",
+ "@0xproject/subproviders": "^1.0.5",
+ "@0xproject/types": "^1.0.1-rc.4",
+ "@0xproject/typescript-typings": "^1.0.4",
+ "@0xproject/utils": "^1.0.5",
+ "@0xproject/web3-wrapper": "^1.2.0",
+ "ethereum-types": "^1.0.4",
+ "ethers": "3.0.22",
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts
index b82cc820f..48d00c1ac 100644
--- a/packages/0x.js/src/0x.ts
+++ b/packages/0x.js/src/0x.ts
@@ -1,26 +1,30 @@
-import { schemas, SchemaValidator } from '@0xproject/json-schemas';
-import { ECSignature, Order, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
-import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils';
+import { assert } from '@0xproject/assert';
+import {
+ ContractWrappers,
+ ContractWrappersConfig,
+ ERC20ProxyWrapper,
+ ERC20TokenWrapper,
+ ERC721ProxyWrapper,
+ ERC721TokenWrapper,
+ EtherTokenWrapper,
+ ExchangeWrapper,
+} from '@0xproject/contract-wrappers';
+import {
+ assetDataUtils,
+ ecSignOrderHashAsync,
+ generatePseudoRandomSalt,
+ isValidSignatureAsync,
+ orderHashUtils,
+} from '@0xproject/order-utils';
+// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
+// in it's public interface, we need to import these types here.
+// tslint:disable-next-line:no-unused-variable
+import { AssetProxyId, ERC20AssetData, ERC721AssetData, Order, SignedOrder, SignerType } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
+import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-import { artifacts } from './artifacts';
-import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
-import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
-import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper';
-import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
-import { TokenWrapper } from './contract_wrappers/token_wrapper';
-import { OrderStateWatcher } from './order_watcher/order_state_watcher';
-import { zeroExConfigSchema } from './schemas/zero_ex_config_schema';
-import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema';
-import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema';
-import { OrderStateWatcherConfig, Web3Provider, ZeroExConfig, ZeroExError } from './types';
-import { assert } from './utils/assert';
import { constants } from './utils/constants';
-import { decorators } from './utils/decorators';
-import { signatureUtils } from './utils/signature_utils';
-import { utils } from './utils/utils';
/**
* The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality
@@ -33,49 +37,34 @@ export class ZeroEx {
* this constant for your convenience.
*/
public static NULL_ADDRESS = constants.NULL_ADDRESS;
-
/**
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
*/
public exchange: ExchangeWrapper;
/**
- * An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x
- * TokenRegistry smart contract.
+ * An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/
- public tokenRegistry: TokenRegistryWrapper;
+ public erc20Token: ERC20TokenWrapper;
/**
- * An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
+ * An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
*/
- public token: TokenWrapper;
+ public erc721Token: ERC721TokenWrapper;
/**
* An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
/**
- * An instance of the TokenTransferProxyWrapper class containing methods for interacting with the
- * tokenTransferProxy smart contract.
+ * An instance of the ERC20ProxyWrapper class containing methods for interacting with the
+ * ERC20 proxy smart contract.
*/
- public proxy: TokenTransferProxyWrapper;
- private _web3Wrapper: Web3Wrapper;
- private _abiDecoder: AbiDecoder;
+ public erc20Proxy: ERC20ProxyWrapper;
/**
- * Verifies that the elliptic curve signature `signature` was generated
- * by signing `data` with the private key corresponding to the `signerAddress` address.
- * @param data The hex encoded data signed by the supplied signature.
- * @param signature An object containing the elliptic curve signature parameters.
- * @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
- * @return Whether the signature is valid for the supplied signerAddress and data.
+ * An instance of the ERC721ProxyWrapper class containing methods for interacting with the
+ * ERC721 proxy smart contract.
*/
- public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
- assert.isHexString('data', data);
- assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
- assert.isETHAddressHex('signerAddress', signerAddress);
- const normalizedSignerAddress = signerAddress.toLowerCase();
-
- const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress);
- return isValidSignature;
- }
+ public erc721Proxy: ERC721ProxyWrapper;
+ private readonly _contractWrappers: ContractWrappers;
/**
* Generates a pseudo-random 256-bit salt.
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
@@ -83,12 +72,15 @@ export class ZeroEx {
* @return A pseudo-random 256-bit number that can be used as a salt.
*/
public static generatePseudoRandomSalt(): BigNumber {
- // BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
- // Source: https://mikemcl.github.io/bignumber.js/#random
- const randomNumber = BigNumber.random(constants.MAX_DIGITS_IN_UNSIGNED_256_INT);
- const factor = new BigNumber(10).pow(constants.MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
- const salt = randomNumber.times(factor).round();
- return salt;
+ return generatePseudoRandomSalt();
+ }
+ /**
+ * Computes the orderHash for a supplied order.
+ * @param order An object that conforms to the Order or SignedOrder interface definitions.
+ * @return The resulting orderHash from hashing the supplied order.
+ */
+ public static getOrderHashHex(order: Order | SignedOrder): string {
+ return orderHashUtils.getOrderHashHex(order);
}
/**
* Checks if the supplied hex encoded order hash is valid.
@@ -98,12 +90,7 @@ export class ZeroEx {
* @return Whether the supplied orderHash has the expected format.
*/
public static isValidOrderHash(orderHash: string): boolean {
- // Since this method can be called to check if any arbitrary string conforms to an orderHash's
- // format, we only assert that we were indeed passed a string.
- assert.isString('orderHash', orderHash);
- const schemaValidator = new SchemaValidator();
- const isValidOrderHash = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
- return isValidOrderHash;
+ return orderHashUtils.isValidOrderHash(orderHash);
}
/**
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
@@ -116,10 +103,8 @@ export class ZeroEx {
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
assert.isValidBaseUnitAmount('amount', amount);
assert.isNumber('decimals', decimals);
-
- const aUnit = new BigNumber(10).pow(decimals);
- const unit = amount.div(aUnit);
- return unit;
+ const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
+ return unitAmount;
}
/**
* A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits
@@ -132,66 +117,93 @@ export class ZeroEx {
public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber {
assert.isBigNumber('amount', amount);
assert.isNumber('decimals', decimals);
-
- const unit = new BigNumber(10).pow(decimals);
- const baseUnitAmount = amount.times(unit);
- const hasDecimals = baseUnitAmount.decimalPlaces() !== 0;
- if (hasDecimals) {
- throw new Error(`Invalid unit amount: ${amount.toString()} - Too many decimal places`);
- }
+ const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
return baseUnitAmount;
}
/**
- * Computes the orderHash for a supplied order.
- * @param order An object that conforms to the Order or SignedOrder interface definitions.
- * @return The resulting orderHash from hashing the supplied order.
+ * Encodes an ERC20 token address into a hex encoded assetData string, usable in the makerAssetData or
+ * takerAssetData fields in a 0x order.
+ * @param tokenAddress The ERC20 token address to encode
+ * @return The hex encoded assetData string
*/
- @decorators.syncZeroExErrorHandler
- public static getOrderHashHex(order: Order | SignedOrder): string {
- assert.doesConformToSchema('order', order, schemas.orderSchema);
- const orderHashHex = utils.getOrderHashHex(order);
- return orderHashHex;
+ public static encodeERC20AssetData(tokenAddress: string): string {
+ return assetDataUtils.encodeERC20AssetData(tokenAddress);
+ }
+ /**
+ * Decodes an ERC20 assetData hex string into it's corresponding ERC20 tokenAddress & assetProxyId
+ * @param assetData Hex encoded assetData string to decode
+ * @return An object containing the decoded tokenAddress & assetProxyId
+ */
+ public static decodeERC20AssetData(assetData: string): ERC20AssetData {
+ return assetDataUtils.decodeERC20AssetData(assetData);
+ }
+ /**
+ * Encodes an ERC721 token address into a hex encoded assetData string, usable in the makerAssetData or
+ * takerAssetData fields in a 0x order.
+ * @param tokenAddress The ERC721 token address to encode
+ * @param tokenId The ERC721 tokenId to encode
+ * @return The hex encoded assetData string
+ */
+ public static encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
+ return assetDataUtils.encodeERC721AssetData(tokenAddress, tokenId);
+ }
+ /**
+ * Decodes an ERC721 assetData hex string into it's corresponding ERC721 tokenAddress, tokenId & assetProxyId
+ * @param assetData Hex encoded assetData string to decode
+ * @return An object containing the decoded tokenAddress, tokenId & assetProxyId
+ */
+ public static decodeERC721AssetData(assetData: string): ERC721AssetData {
+ return assetDataUtils.decodeERC721AssetData(assetData);
+ }
+ /**
+ * Decode and return the assetProxyId from the assetData
+ * @param assetData Hex encoded assetData string to decode
+ * @return The assetProxyId
+ */
+ public static decodeAssetProxyId(assetData: string): AssetProxyId {
+ return assetDataUtils.decodeAssetProxyId(assetData);
+ }
+ /**
+ * Decode any assetData into it's corresponding assetData object
+ * @param assetData Hex encoded assetData string to decode
+ * @return Either a ERC20 or ERC721 assetData object
+ */
+ public static decodeAssetDataOrThrow(assetData: string): ERC20AssetData | ERC721AssetData {
+ return assetDataUtils.decodeAssetDataOrThrow(assetData);
}
/**
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
- * @param provider The Web3.js Provider instance you would like the 0x.js library to use for interacting with
+ * @param provider The Provider instance you would like the 0x.js library to use for interacting with
* the Ethereum network.
* @param config The configuration object. Look up the type for the description.
* @return An instance of the 0x.js ZeroEx class.
*/
- constructor(provider: Web3Provider, config: ZeroExConfig) {
+ constructor(provider: Provider, config: ContractWrappersConfig) {
assert.isWeb3Provider('provider', provider);
- assert.doesConformToSchema('config', config, zeroExConfigSchema, [
- zeroExPrivateNetworkConfigSchema,
- zeroExPublicNetworkConfigSchema,
- ]);
- const artifactJSONs = _.values(artifacts);
- const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
- this._abiDecoder = new AbiDecoder(abiArrays);
- const defaults = {
- gasPrice: config.gasPrice,
- };
- this._web3Wrapper = new Web3Wrapper(provider, defaults);
- this.proxy = new TokenTransferProxyWrapper(
- this._web3Wrapper,
- config.networkId,
- config.tokenTransferProxyContractAddress,
- );
- this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this._abiDecoder, this.proxy);
- this.exchange = new ExchangeWrapper(
- this._web3Wrapper,
- config.networkId,
- this._abiDecoder,
- this.token,
- config.exchangeContractAddress,
- config.zrxContractAddress,
- );
- this.tokenRegistry = new TokenRegistryWrapper(
- this._web3Wrapper,
- config.networkId,
- config.tokenRegistryContractAddress,
+ this._contractWrappers = new ContractWrappers(provider, config);
+
+ this.erc20Proxy = this._contractWrappers.erc20Proxy;
+ this.erc721Proxy = this._contractWrappers.erc721Proxy;
+ this.erc20Token = this._contractWrappers.erc20Token;
+ this.erc721Token = this._contractWrappers.erc721Token;
+ this.exchange = this._contractWrappers.exchange;
+ this.etherToken = this._contractWrappers.etherToken;
+ }
+ /**
+ * Verifies that the provided signature is valid according to the 0x Protocol smart contracts
+ * @param data The hex encoded data signed by the supplied signature.
+ * @param signature The hex encoded signature.
+ * @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
+ * @return Whether the signature is valid for the supplied signerAddress and data.
+ */
+ public async isValidSignatureAsync(data: string, signature: string, signerAddress: string): Promise<boolean> {
+ const isValid = await isValidSignatureAsync(
+ this._contractWrappers.getProvider(),
+ data,
+ signature,
+ signerAddress,
);
- this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this._abiDecoder, this.token);
+ return isValid;
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
@@ -199,25 +211,24 @@ export class ZeroEx {
* @param provider The Web3Provider you would like the 0x.js library to use from now on.
* @param networkId The id of the network your provider is connected to
*/
- public setProvider(provider: Web3Provider, networkId: number): void {
- this._web3Wrapper.setProvider(provider);
- (this.exchange as any)._invalidateContractInstances();
- (this.exchange as any)._setNetworkId(networkId);
- (this.tokenRegistry as any)._invalidateContractInstance();
- (this.tokenRegistry as any)._setNetworkId(networkId);
- (this.token as any)._invalidateContractInstances();
- (this.token as any)._setNetworkId(networkId);
- (this.proxy as any)._invalidateContractInstance();
- (this.proxy as any)._setNetworkId(networkId);
- (this.etherToken as any)._invalidateContractInstance();
- (this.etherToken as any)._setNetworkId(networkId);
+ public setProvider(provider: Provider, networkId: number): void {
+ this._contractWrappers.setProvider(provider, networkId);
+ }
+ /**
+ * Get the provider instance currently used by 0x.js
+ * @return Web3 provider instance
+ */
+ public getProvider(): Provider {
+ return this._contractWrappers.getProvider();
}
/**
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
* @return An array of available user Ethereum addresses.
*/
public async getAvailableAddressesAsync(): Promise<string[]> {
- const availableAddresses = await this._web3Wrapper.getAvailableAddressesAsync();
+ // Hack: Get Web3Wrapper from ContractWrappers
+ const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
+ const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
return availableAddresses;
}
/**
@@ -225,53 +236,24 @@ export class ZeroEx {
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
* @param orderHash Hex encoded orderHash to sign.
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
- * must be available via the Web3.Provider supplied to 0x.js.
- * @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message`
- * themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client
- * (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix
- * before sending the request.
- * @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
+ * must be available via the Provider supplied to 0x.js.
+ * @param signerType the signer type that will perform the `eth_sign` operation. E.g Default, Metamask, Ledger or Trezor.
+ * Some implementations exhibit different behaviour. Default will assume a spec compliant eth_sign implementation.
+ * This parameter is defaulted to `SignerType.Default`.
+ * @return A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type.
*/
- public async signOrderHashAsync(
+ public async ecSignOrderHashAsync(
orderHash: string,
signerAddress: string,
- shouldAddPersonalMessagePrefix: boolean,
- ): Promise<ECSignature> {
- assert.isHexString('orderHash', orderHash);
- await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
- const normalizedSignerAddress = signerAddress.toLowerCase();
-
- let msgHashHex = orderHash;
- if (shouldAddPersonalMessagePrefix) {
- const orderHashBuff = ethUtil.toBuffer(orderHash);
- const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
- msgHashHex = ethUtil.bufferToHex(msgHashBuff);
- }
-
- const signature = await this._web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
-
- // HACK: There is no consensus on whether the signatureHex string should be formatted as
- // v + r + s OR r + s + v, and different clients (even different versions of the same client)
- // return the signature params in different orders. In order to support all client implementations,
- // we parse the signature in both ways, and evaluate if either one is a valid signature.
- const validVParamValues = [27, 28];
- const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
- if (_.includes(validVParamValues, ecSignatureVRS.v)) {
- const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
- if (isValidVRSSignature) {
- return ecSignatureVRS;
- }
- }
-
- const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
- if (_.includes(validVParamValues, ecSignatureRSV.v)) {
- const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
- if (isValidRSVSignature) {
- return ecSignatureRSV;
- }
- }
-
- throw new Error(ZeroExError.InvalidSignature);
+ signerType: SignerType = SignerType.Default,
+ ): Promise<string> {
+ const signature = await ecSignOrderHashAsync(
+ this._contractWrappers.getProvider(),
+ orderHash,
+ signerAddress,
+ signerType,
+ );
+ return signature;
}
/**
* Waits for a transaction to be mined and returns the transaction receipt.
@@ -282,65 +264,16 @@ export class ZeroEx {
*/
public async awaitTransactionMinedAsync(
txHash: string,
- pollingIntervalMs = 1000,
+ pollingIntervalMs: number = 1000,
timeoutMs?: number,
): Promise<TransactionReceiptWithDecodedLogs> {
- let timeoutExceeded = false;
- if (timeoutMs) {
- setTimeout(() => (timeoutExceeded = true), timeoutMs);
- }
-
- const txReceiptPromise = new Promise(
- (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
- const intervalId = intervalUtils.setAsyncExcludingInterval(
- async () => {
- if (timeoutExceeded) {
- intervalUtils.clearAsyncExcludingInterval(intervalId);
- return reject(ZeroExError.TransactionMiningTimeout);
- }
-
- const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
- if (!_.isNull(transactionReceipt)) {
- intervalUtils.clearAsyncExcludingInterval(intervalId);
- const logsWithDecodedArgs = _.map(
- transactionReceipt.logs,
- this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
- );
- const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
- ...transactionReceipt,
- logs: logsWithDecodedArgs,
- };
- resolve(transactionReceiptWithDecodedLogArgs);
- }
- },
- pollingIntervalMs,
- (err: Error) => {
- intervalUtils.clearAsyncExcludingInterval(intervalId);
- reject(err);
- },
- );
- },
+ // Hack: Get Web3Wrapper from ContractWrappers
+ const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
+ const transactionReceiptWithDecodedLogs = await web3Wrapper.awaitTransactionMinedAsync(
+ txHash,
+ pollingIntervalMs,
+ timeoutMs,
);
- const txReceipt = await txReceiptPromise;
- return txReceipt;
- }
- /**
- * Instantiates and returns a new OrderStateWatcher instance.
- * Defaults to watching the pending state.
- * @param config The configuration object. Look up the type for the description.
- * @return An instance of the 0x.js OrderStateWatcher class.
- */
- public createOrderStateWatcher(config?: OrderStateWatcherConfig) {
- return new OrderStateWatcher(this._web3Wrapper, this._abiDecoder, this.token, this.exchange, config);
- }
- /*
- * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from
- * an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle.
- * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper`
- * and `ProxyWrapper`.
- */
- private async _getTokenTransferProxyAddressAsync(): Promise<string> {
- const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync();
- return tokenTransferProxyAddress;
+ return transactionReceiptWithDecodedLogs;
}
}
diff --git a/packages/0x.js/src/artifacts.ts b/packages/0x.js/src/artifacts.ts
index cbacd7d56..f68969d28 100644
--- a/packages/0x.js/src/artifacts.ts
+++ b/packages/0x.js/src/artifacts.ts
@@ -1,18 +1,7 @@
-import * as DummyTokenArtifact from './artifacts/DummyToken.json';
-import * as EtherTokenArtifact from './artifacts/EtherToken.json';
-import * as ExchangeArtifact from './artifacts/Exchange.json';
-import * as TokenArtifact from './artifacts/Token.json';
-import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
-import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
-import * as ZRXArtifact from './artifacts/ZRX.json';
-import { Artifact } from './types';
+import { ContractArtifact } from '@0xproject/sol-compiler';
+
+import * as ZRXToken from './artifacts/ZRXToken.json';
export const artifacts = {
- ZRXArtifact: (ZRXArtifact as any) as Artifact,
- DummyTokenArtifact: (DummyTokenArtifact as any) as Artifact,
- TokenArtifact: (TokenArtifact as any) as Artifact,
- ExchangeArtifact: (ExchangeArtifact as any) as Artifact,
- EtherTokenArtifact: (EtherTokenArtifact as any) as Artifact,
- TokenRegistryArtifact: (TokenRegistryArtifact as any) as Artifact,
- TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as Artifact,
+ ZRXToken: (ZRXToken as any) as ContractArtifact,
};
diff --git a/packages/0x.js/src/artifacts/DummyToken.json b/packages/0x.js/src/artifacts/DummyToken.json
deleted file mode 100644
index f64a8cd3d..000000000
--- a/packages/0x.js/src/artifacts/DummyToken.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "contract_name": "DummyToken",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_target",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "setBalance",
- "outputs": [],
- "payable": false,
- "type": "function"
- }
- ]
-}
diff --git a/packages/0x.js/src/artifacts/EtherToken.json b/packages/0x.js/src/artifacts/EtherToken.json
deleted file mode 100644
index 26cca57cd..000000000
--- a/packages/0x.js/src/artifacts/EtherToken.json
+++ /dev/null
@@ -1,287 +0,0 @@
-{
- "contract_name": "EtherToken",
- "abi": [
- {
- "constant": true,
- "inputs": [],
- "name": "name",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
- },
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "withdraw",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "decimals",
- "outputs": [
- {
- "name": "",
- "type": "uint8"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "symbol",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "deposit",
- "outputs": [],
- "payable": true,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- },
- {
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "payable": true,
- "type": "fallback"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_spender",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Deposit",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Withdrawal",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
- },
- "3": {
- "address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
- },
- "4": {
- "address": "0xc778417e063141139fce010982780140aa0cd5ab"
- },
- "42": {
- "address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
- },
- "50": {
- "address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
- }
- }
-}
diff --git a/packages/0x.js/src/artifacts/Exchange.json b/packages/0x.js/src/artifacts/Exchange.json
deleted file mode 100644
index af8db7360..000000000
--- a/packages/0x.js/src/artifacts/Exchange.json
+++ /dev/null
@@ -1,610 +0,0 @@
-{
- "contract_name": "Exchange",
- "abi": [
- {
- "constant": true,
- "inputs": [
- {
- "name": "numerator",
- "type": "uint256"
- },
- {
- "name": "denominator",
- "type": "uint256"
- },
- {
- "name": "target",
- "type": "uint256"
- }
- ],
- "name": "isRoundingError",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "name": "filled",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "name": "cancelled",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "fillOrdersUpTo",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "cancelTakerTokenAmount",
- "type": "uint256"
- }
- ],
- "name": "cancelOrder",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "ZRX_TOKEN_CONTRACT",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmounts",
- "type": "uint256[]"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "batchFillOrKillOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "fillOrKillOrder",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "orderHash",
- "type": "bytes32"
- }
- ],
- "name": "getUnavailableTakerTokenAmount",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "signer",
- "type": "address"
- },
- {
- "name": "hash",
- "type": "bytes32"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "isValidSignature",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "numerator",
- "type": "uint256"
- },
- {
- "name": "denominator",
- "type": "uint256"
- },
- {
- "name": "target",
- "type": "uint256"
- }
- ],
- "name": "getPartialAmount",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "TOKEN_TRANSFER_PROXY_CONTRACT",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmounts",
- "type": "uint256[]"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "batchFillOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "cancelTakerTokenAmounts",
- "type": "uint256[]"
- }
- ],
- "name": "batchCancelOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "fillOrder",
- "outputs": [
- {
- "name": "filledTakerTokenAmount",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- }
- ],
- "name": "getOrderHash",
- "outputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "EXTERNAL_QUERY_GAS_LIMIT",
- "outputs": [
- {
- "name": "",
- "type": "uint16"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "VERSION",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "inputs": [
- {
- "name": "_zrxToken",
- "type": "address"
- },
- {
- "name": "_tokenTransferProxy",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "constructor"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "maker",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "taker",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "feeRecipient",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "makerToken",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "takerToken",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "filledMakerTokenAmount",
- "type": "uint256"
- },
- {
- "indexed": false,
- "name": "filledTakerTokenAmount",
- "type": "uint256"
- },
- {
- "indexed": false,
- "name": "paidMakerFee",
- "type": "uint256"
- },
- {
- "indexed": false,
- "name": "paidTakerFee",
- "type": "uint256"
- },
- {
- "indexed": true,
- "name": "tokens",
- "type": "bytes32"
- },
- {
- "indexed": false,
- "name": "orderHash",
- "type": "bytes32"
- }
- ],
- "name": "LogFill",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "maker",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "feeRecipient",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "makerToken",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "takerToken",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "cancelledMakerTokenAmount",
- "type": "uint256"
- },
- {
- "indexed": false,
- "name": "cancelledTakerTokenAmount",
- "type": "uint256"
- },
- {
- "indexed": true,
- "name": "tokens",
- "type": "bytes32"
- },
- {
- "indexed": false,
- "name": "orderHash",
- "type": "bytes32"
- }
- ],
- "name": "LogCancel",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "errorId",
- "type": "uint8"
- },
- {
- "indexed": true,
- "name": "orderHash",
- "type": "bytes32"
- }
- ],
- "name": "LogError",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0x12459c951127e0c374ff9105dda097662a027093"
- },
- "3": {
- "address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
- },
- "4": {
- "address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
- },
- "42": {
- "address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
- },
- "50": {
- "address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
- }
- }
-}
diff --git a/packages/0x.js/src/artifacts/Token.json b/packages/0x.js/src/artifacts/Token.json
deleted file mode 100644
index 3b5a86ae0..000000000
--- a/packages/0x.js/src/artifacts/Token.json
+++ /dev/null
@@ -1,172 +0,0 @@
-{
- "contract_name": "Token",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "supply",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
- },
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "balance",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- },
- {
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "remaining",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_spender",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- }
- ]
-}
diff --git a/packages/0x.js/src/artifacts/TokenRegistry.json b/packages/0x.js/src/artifacts/TokenRegistry.json
deleted file mode 100644
index 0f583628c..000000000
--- a/packages/0x.js/src/artifacts/TokenRegistry.json
+++ /dev/null
@@ -1,547 +0,0 @@
-{
- "contract_name": "TokenRegistry",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_index",
- "type": "uint256"
- }
- ],
- "name": "removeToken",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "getTokenAddressByName",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "getTokenAddressBySymbol",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_swarmHash",
- "type": "bytes"
- }
- ],
- "name": "setTokenSwarmHash",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- }
- ],
- "name": "getTokenMetaData",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "owner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_name",
- "type": "string"
- },
- {
- "name": "_symbol",
- "type": "string"
- },
- {
- "name": "_decimals",
- "type": "uint8"
- },
- {
- "name": "_ipfsHash",
- "type": "bytes"
- },
- {
- "name": "_swarmHash",
- "type": "bytes"
- }
- ],
- "name": "addToken",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "setTokenName",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "name": "tokens",
- "outputs": [
- {
- "name": "token",
- "type": "address"
- },
- {
- "name": "name",
- "type": "string"
- },
- {
- "name": "symbol",
- "type": "string"
- },
- {
- "name": "decimals",
- "type": "uint8"
- },
- {
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "tokenAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "getTokenByName",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getTokenAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address[]"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_ipfsHash",
- "type": "bytes"
- }
- ],
- "name": "setTokenIpfsHash",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "getTokenBySymbol",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "setTokenSymbol",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "name",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "symbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "decimals",
- "type": "uint8"
- },
- {
- "indexed": false,
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogAddToken",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "name",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "symbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "decimals",
- "type": "uint8"
- },
- {
- "indexed": false,
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogRemoveToken",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldName",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "newName",
- "type": "string"
- }
- ],
- "name": "LogTokenNameChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldSymbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "newSymbol",
- "type": "string"
- }
- ],
- "name": "LogTokenSymbolChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldIpfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "newIpfsHash",
- "type": "bytes"
- }
- ],
- "name": "LogTokenIpfsHashChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldSwarmHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "newSwarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogTokenSwarmHashChange",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
- },
- "3": {
- "address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
- },
- "4": {
- "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
- },
- "42": {
- "address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
- },
- "50": {
- "address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
- }
- }
-}
diff --git a/packages/0x.js/src/artifacts/TokenTransferProxy.json b/packages/0x.js/src/artifacts/TokenTransferProxy.json
deleted file mode 100644
index 8cf551ddb..000000000
--- a/packages/0x.js/src/artifacts/TokenTransferProxy.json
+++ /dev/null
@@ -1,187 +0,0 @@
-{
- "contract_name": "TokenTransferProxy",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "token",
- "type": "address"
- },
- {
- "name": "from",
- "type": "address"
- },
- {
- "name": "to",
- "type": "address"
- },
- {
- "name": "value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "target",
- "type": "address"
- }
- ],
- "name": "addAuthorizedAddress",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "authorities",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "target",
- "type": "address"
- }
- ],
- "name": "removeAuthorizedAddress",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "owner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "name": "authorized",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getAuthorizedAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address[]"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "target",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "caller",
- "type": "address"
- }
- ],
- "name": "LogAuthorizedAddressAdded",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "target",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "caller",
- "type": "address"
- }
- ],
- "name": "LogAuthorizedAddressRemoved",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
- },
- "3": {
- "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
- },
- "4": {
- "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
- },
- "42": {
- "address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
- },
- "50": {
- "address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
- }
- }
-}
diff --git a/packages/0x.js/src/artifacts/ZRX.json b/packages/0x.js/src/artifacts/ZRX.json
deleted file mode 100644
index e40b8f268..000000000
--- a/packages/0x.js/src/artifacts/ZRX.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "contract_name": "ZRX",
- "networks": {
- "1": {
- "address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
- },
- "3": {
- "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
- },
- "4": {
- "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
- },
- "42": {
- "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
- },
- "50": {
- "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
- }
- }
-}
diff --git a/packages/0x.js/src/artifacts/ZRXToken.json b/packages/0x.js/src/artifacts/ZRXToken.json
new file mode 100644
index 000000000..0ce91c1c1
--- /dev/null
+++ b/packages/0x.js/src/artifacts/ZRXToken.json
@@ -0,0 +1,10031 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "ZRXToken",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "name": "_spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "methods": {
+ "transferFrom(address,address,uint256)": {
+ "details": "ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.",
+ "params": {
+ "_from": "Address to transfer from.",
+ "_to": "Address to transfer to.",
+ "_value": "Amount to transfer."
+ },
+ "return": "Success of transfer."
+ }
+ }
+ },
+ "evm": {
+ "assembly": " /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":795:1242 contract ZRXToken is UnlimitedAllowanceToken {... */\n mstore(0x40, 0x60)\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":958:964 10**27 */\n 0x33b2e3c9fd0803ce8000000\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":932:964 uint public totalSupply = 10**27 */\n 0x3\n sstore\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1150:1240 function ZRXToken()... */\n jumpi(tag_1, iszero(callvalue))\n invalid\ntag_1:\ntag_2:\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1222:1233 totalSupply */\n sload(0x3)\n sub(exp(0x2, 0xa0), 0x1)\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1208:1218 msg.sender */\n caller\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1199:1219 balances[msg.sender] */\n and\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1199:1207 balances */\n 0x0\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1199:1219 balances[msg.sender] */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n swap1\n sha3\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1199:1233 balances[msg.sender] = totalSupply */\n sstore\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1150:1240 function ZRXToken()... */\ntag_3:\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":795:1242 contract ZRXToken is UnlimitedAllowanceToken {... */\ntag_4:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n return\nstop\n\nsub_0: assembly {\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":795:1242 contract ZRXToken is UnlimitedAllowanceToken {... */\n mstore(0x40, 0x60)\n jumpi(tag_1, iszero(calldatasize))\n and(div(calldataload(0x0), 0x100000000000000000000000000000000000000000000000000000000), 0xffffffff)\n 0x6fdde03\n dup2\n eq\n tag_2\n jumpi\n dup1\n 0x95ea7b3\n eq\n tag_3\n jumpi\n dup1\n 0x18160ddd\n eq\n tag_4\n jumpi\n dup1\n 0x23b872dd\n eq\n tag_5\n jumpi\n dup1\n 0x313ce567\n eq\n tag_6\n jumpi\n dup1\n 0x70a08231\n eq\n tag_7\n jumpi\n dup1\n 0x95d89b41\n eq\n tag_8\n jumpi\n dup1\n 0xa9059cbb\n eq\n tag_9\n jumpi\n dup1\n 0xdd62ed3e\n eq\n tag_10\n jumpi\n tag_1:\n invalid\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1009:1058 string constant public name = \"0x Protocol Token\" */\n tag_2:\n jumpi(tag_11, iszero(callvalue))\n invalid\n tag_11:\n tag_12\n jump(tag_13)\n tag_12:\n 0x40\n dup1\n mload\n 0x20\n dup1\n dup3\n mstore\n dup4\n mload\n dup2\n dup4\n add\n mstore\n dup4\n mload\n swap2\n swap3\n dup4\n swap3\n swap1\n dup4\n add\n swap2\n dup6\n add\n swap1\n dup1\n dup4\n dup4\n /* \"--CODEGEN--\":18:20 */\n dup3\n iszero\n /* \"--CODEGEN--\":13:16 */\n tag_14\n /* \"--CODEGEN--\":7:12 */\n jumpi\n /* \"--CODEGEN--\":32:37 */\n tag_15:\n /* \"--CODEGEN--\":59:62 */\n dup1\n /* \"--CODEGEN--\":53:58 */\n mload\n /* \"--CODEGEN--\":48:51 */\n dup3\n /* \"--CODEGEN--\":41:47 */\n mstore\n /* \"--CODEGEN--\":93:95 */\n 0x20\n /* \"--CODEGEN--\":88:91 */\n dup4\n /* \"--CODEGEN--\":85:87 */\n gt\n /* \"--CODEGEN--\":78:84 */\n iszero\n /* \"--CODEGEN--\":73:76 */\n tag_14\n /* \"--CODEGEN--\":67:72 */\n jumpi\n /* \"--CODEGEN--\":152:155 */\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0\n swap1\n swap3\n add\n swap2\n /* \"--CODEGEN--\":117:119 */\n 0x20\n /* \"--CODEGEN--\":108:111 */\n swap2\n dup3\n add\n swap2\n /* \"--CODEGEN--\":130:133 */\n add\n /* \"--CODEGEN--\":172:177 */\n tag_15\n /* \"--CODEGEN--\":167:171 */\n jump\n /* \"--CODEGEN--\":181:184 */\n tag_14:\n /* \"--CODEGEN--\":3:189 */\n pop\n pop\n pop\n swap1\n pop\n swap1\n dup2\n add\n swap1\n 0x1f\n and\n dup1\n iszero\n tag_16\n jumpi\n dup1\n dup3\n sub\n dup1\n mload\n 0x1\n dup4\n 0x20\n sub\n 0x100\n exp\n sub\n not\n and\n dup2\n mstore\n 0x20\n add\n swap2\n pop\n tag_16:\n pop\n swap3\n pop\n pop\n pop\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n return\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1087:1274 */\n tag_3:\n jumpi(tag_17, iszero(callvalue))\n invalid\n tag_17:\n tag_18\n and(calldataload(0x4), 0xffffffffffffffffffffffffffffffffffffffff)\n calldataload(0x24)\n jump(tag_19)\n tag_18:\n 0x40\n dup1\n mload\n swap2\n iszero\n iszero\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":932:964 uint public totalSupply = 10**27 */\n tag_4:\n jumpi(tag_20, iszero(callvalue))\n invalid\n tag_20:\n tag_21\n jump(tag_22)\n tag_21:\n 0x40\n dup1\n mload\n swap2\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1066:1675 */\n tag_5:\n jumpi(tag_23, iszero(callvalue))\n invalid\n tag_23:\n tag_18\n 0xffffffffffffffffffffffffffffffffffffffff\n calldataload(0x4)\n dup2\n and\n swap1\n calldataload(0x24)\n and\n calldataload(0x44)\n jump(tag_25)\n tag_24:\n 0x40\n dup1\n mload\n swap2\n iszero\n iszero\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":891:926 uint8 constant public decimals = 18 */\n tag_6:\n jumpi(tag_26, iszero(callvalue))\n invalid\n tag_26:\n tag_27\n jump(tag_28)\n tag_27:\n 0x40\n dup1\n mload\n 0xff\n swap1\n swap3\n and\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":982:1081 */\n tag_7:\n jumpi(tag_29, iszero(callvalue))\n invalid\n tag_29:\n tag_21\n and(calldataload(0x4), 0xffffffffffffffffffffffffffffffffffffffff)\n jump(tag_31)\n tag_30:\n 0x40\n dup1\n mload\n swap2\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1064:1101 string constant public symbol = \"ZRX\" */\n tag_8:\n jumpi(tag_32, iszero(callvalue))\n invalid\n tag_32:\n tag_12\n jump(tag_34)\n tag_33:\n 0x40\n dup1\n mload\n 0x20\n dup1\n dup3\n mstore\n dup4\n mload\n dup2\n dup4\n add\n mstore\n dup4\n mload\n swap2\n swap3\n dup4\n swap3\n swap1\n dup4\n add\n swap2\n dup6\n add\n swap1\n dup1\n dup4\n dup4\n /* \"--CODEGEN--\":18:20 */\n dup3\n iszero\n /* \"--CODEGEN--\":13:16 */\n tag_14\n /* \"--CODEGEN--\":7:12 */\n jumpi\n /* \"--CODEGEN--\":32:37 */\n tag_36:\n /* \"--CODEGEN--\":59:62 */\n dup1\n /* \"--CODEGEN--\":53:58 */\n mload\n /* \"--CODEGEN--\":48:51 */\n dup3\n /* \"--CODEGEN--\":41:47 */\n mstore\n /* \"--CODEGEN--\":93:95 */\n 0x20\n /* \"--CODEGEN--\":88:91 */\n dup4\n /* \"--CODEGEN--\":85:87 */\n gt\n /* \"--CODEGEN--\":78:84 */\n iszero\n /* \"--CODEGEN--\":73:76 */\n tag_14\n /* \"--CODEGEN--\":67:72 */\n jumpi\n /* \"--CODEGEN--\":152:155 */\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0\n swap1\n swap3\n add\n swap2\n /* \"--CODEGEN--\":117:119 */\n 0x20\n /* \"--CODEGEN--\":108:111 */\n swap2\n dup3\n add\n swap2\n /* \"--CODEGEN--\":130:133 */\n add\n /* \"--CODEGEN--\":172:177 */\n tag_15\n /* \"--CODEGEN--\":167:171 */\n jump\n /* \"--CODEGEN--\":181:184 */\n tag_35:\n /* \"--CODEGEN--\":3:189 */\n pop\n pop\n pop\n swap1\n pop\n swap1\n dup2\n add\n swap1\n 0x1f\n and\n dup1\n iszero\n tag_16\n jumpi\n dup1\n dup3\n sub\n dup1\n mload\n 0x1\n dup4\n 0x20\n sub\n 0x100\n exp\n sub\n not\n and\n dup2\n mstore\n 0x20\n add\n swap2\n pop\n tag_37:\n pop\n swap3\n pop\n pop\n pop\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n return\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":125:535 */\n tag_9:\n jumpi(tag_38, iszero(callvalue))\n invalid\n tag_38:\n tag_18\n and(calldataload(0x4), 0xffffffffffffffffffffffffffffffffffffffff)\n calldataload(0x24)\n jump(tag_40)\n tag_39:\n 0x40\n dup1\n mload\n swap2\n iszero\n iszero\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1280:1406 */\n tag_10:\n jumpi(tag_41, iszero(callvalue))\n invalid\n tag_41:\n tag_21\n 0xffffffffffffffffffffffffffffffffffffffff\n calldataload(0x4)\n dup2\n and\n swap1\n calldataload(0x24)\n and\n jump(tag_43)\n tag_42:\n 0x40\n dup1\n mload\n swap2\n dup3\n mstore\n mload\n swap1\n dup2\n swap1\n sub\n 0x20\n add\n swap1\n return\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1009:1058 string constant public name = \"0x Protocol Token\" */\n tag_13:\n 0x40\n dup1\n mload\n dup1\n dup3\n add\n swap1\n swap2\n mstore\n 0x11\n dup2\n mstore\n 0x30782050726f746f636f6c20546f6b656e000000000000000000000000000000\n 0x20\n dup3\n add\n mstore\n dup2\n jump\t// out\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1087:1274 */\n tag_19:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1179 */\n 0xffffffffffffffffffffffffffffffffffffffff\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1168:1178 */\n caller\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1179 */\n dup2\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1144:1148 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1179 */\n dup2\n dup2\n mstore\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1167 */\n 0x1\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1179 */\n 0x20\n swap1\n dup2\n mstore\n 0x40\n dup1\n dup4\n sha3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1189 */\n swap5\n dup8\n and\n dup1\n dup5\n mstore\n swap5\n dup3\n mstore\n dup1\n dup4\n sha3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1198 */\n dup7\n swap1\n sstore\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1208:1246 */\n dup1\n mload\n dup7\n dup2\n mstore\n swap1\n mload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1144:1148 */\n swap3\n swap5\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1189 */\n swap4\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1160:1179 */\n swap3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1208:1246 */\n 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\n swap3\n swap2\n dup2\n swap1\n sub\n swap1\n swap2\n add\n swap1\n log3\n pop\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1263:1267 */\n 0x1\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1087:1274 */\n tag_44:\n swap3\n swap2\n pop\n pop\n jump\t// out\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":932:964 uint public totalSupply = 10**27 */\n tag_22:\n sload(0x3)\n dup2\n jump\t// out\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1066:1675 */\n tag_25:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1198:1212 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup1\n dup5\n and\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1161:1165 */\n 0x0\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1198:1212 */\n dup2\n dup2\n mstore\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1198:1205 */\n 0x1\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1198:1212 */\n 0x20\n swap1\n dup2\n mstore\n 0x40\n dup1\n dup4\n sha3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1213:1223 */\n caller\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1198:1224 */\n swap1\n swap6\n and\n dup4\n mstore\n swap4\n dup2\n mstore\n dup4\n dup3\n sha3\n sload\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1253 */\n swap3\n dup3\n mstore\n dup2\n swap1\n mstore\n swap2\n dup3\n sha3\n sload\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1263 */\n dup4\n swap1\n lt\n dup1\n iszero\n swap1\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1298 */\n tag_46\n jumpi\n pop\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1292:1298 */\n dup3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1279:1288 */\n dup2\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1279:1298 */\n lt\n iszero\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1298 */\n tag_46:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1353 */\n dup1\n iszero\n tag_47\n jumpi\n pop\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1340:1353 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup5\n and\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1340:1348 */\n 0x0\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1340:1353 */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n swap1\n sha3\n sload\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1314:1336 */\n dup4\n dup2\n add\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1314:1353 */\n lt\n iszero\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1238:1353 */\n tag_47:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1234:1669 */\n iszero\n tag_48\n jumpi\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1378:1391 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup1\n dup6\n and\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1378:1386 */\n 0x0\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1378:1391 */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n dup1\n dup3\n sha3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1378:1401 */\n dup1\n sload\n dup8\n add\n swap1\n sstore\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1415:1430 */\n swap2\n dup8\n and\n dup2\n mstore\n sha3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1415:1440 */\n dup1\n sload\n dup5\n swap1\n sub\n swap1\n sstore\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":768:778 */\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1458:1478 */\n dup2\n lt\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1454:1549 */\n iszero\n tag_49\n jumpi\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1498:1512 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup1\n dup7\n and\n 0x0\n swap1\n dup2\n mstore\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1498:1505 */\n 0x1\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1498:1512 */\n 0x20\n swap1\n dup2\n mstore\n 0x40\n dup1\n dup4\n sha3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1513:1523 */\n caller\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1498:1524 */\n swap1\n swap5\n and\n dup4\n mstore\n swap3\n swap1\n mstore\n sha3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1498:1534 */\n dup1\n sload\n dup5\n swap1\n sub\n swap1\n sstore\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1454:1549 */\n tag_49:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1578:1581 */\n dup4\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1562:1590 */\n 0xffffffffffffffffffffffffffffffffffffffff\n and\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1571:1576 */\n dup6\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1562:1590 */\n 0xffffffffffffffffffffffffffffffffffffffff\n and\n 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1583:1589 */\n dup6\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1562:1590 */\n mload(0x40)\n dup1\n dup3\n dup2\n mstore\n 0x20\n add\n swap2\n pop\n pop\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n log3\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1611:1615 */\n 0x1\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1604:1615 */\n swap2\n pop\n jump(tag_50)\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1234:1669 */\n tag_48:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1653:1658 */\n 0x0\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1646:1658 */\n swap2\n pop\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1234:1669 */\n tag_50:\n /* \"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":1066:1675 */\n tag_45:\n pop\n swap4\n swap3\n pop\n pop\n pop\n jump\t// out\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":891:926 uint8 constant public decimals = 18 */\n tag_28:\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":924:926 18 */\n 0x12\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":891:926 uint8 constant public decimals = 18 */\n dup2\n jump\t// out\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":982:1081 */\n tag_31:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1058:1074 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup2\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1035:1039 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1058:1074 */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n swap1\n sha3\n sload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":982:1081 */\n tag_51:\n swap2\n swap1\n pop\n jump\t// out\n /* \"2.0.0/tokens/ZRXToken/ZRXToken.sol\":1064:1101 string constant public symbol = \"ZRX\" */\n tag_34:\n 0x40\n dup1\n mload\n dup1\n dup3\n add\n swap1\n swap2\n mstore\n 0x3\n dup2\n mstore\n 0x5a52580000000000000000000000000000000000000000000000000000000000\n 0x20\n dup3\n add\n mstore\n dup2\n jump\t// out\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":125:535 */\n tag_40:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:287 */\n 0xffffffffffffffffffffffffffffffffffffffff\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":276:286 */\n caller\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:287 */\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":178:182 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:287 */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n dup2\n sha3\n sload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:297 */\n dup3\n swap1\n lt\n dup1\n iszero\n swap1\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:340 */\n tag_53\n jumpi\n pop\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":327:340 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup4\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":327:335 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":327:340 */\n swap1\n dup2\n mstore\n 0x20\n dup2\n swap1\n mstore\n 0x40\n swap1\n sha3\n sload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":301:323 */\n dup3\n dup2\n add\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":301:340 */\n lt\n iszero\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":267:340 */\n tag_53:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":263:529 */\n iszero\n tag_54\n jumpi\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":356:376 */\n 0xffffffffffffffffffffffffffffffffffffffff\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":365:375 */\n caller\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":356:376 */\n dup2\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":356:364 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":356:376 */\n dup2\n dup2\n mstore\n 0x20\n dup2\n dup2\n mstore\n 0x40\n dup1\n dup4\n sha3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":356:386 */\n dup1\n sload\n dup9\n swap1\n sub\n swap1\n sstore\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":400:413 */\n swap4\n dup8\n and\n dup1\n dup4\n mstore\n swap2\n dup5\n swap1\n sha3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":400:423 */\n dup1\n sload\n dup8\n add\n swap1\n sstore\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":437:470 */\n dup4\n mload\n dup7\n dup2\n mstore\n swap4\n mload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":400:413 */\n swap2\n swap4\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":437:470 */\n 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\n swap3\n swap1\n dup2\n swap1\n sub\n swap1\n swap2\n add\n swap1\n log3\n pop\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":491:495 */\n 0x1\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":484:495 */\n jump(tag_44)\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":263:529 */\n tag_54:\n pop\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":521:526 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":514:526 */\n jump(tag_44)\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":263:529 */\n tag_55:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":125:535 */\n tag_52:\n swap3\n swap2\n pop\n pop\n jump\t// out\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1280:1406 */\n tag_43:\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1374:1389 */\n 0xffffffffffffffffffffffffffffffffffffffff\n dup1\n dup4\n and\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1351:1355 */\n 0x0\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1374:1389 */\n swap1\n dup2\n mstore\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1374:1381 */\n 0x1\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1374:1389 */\n 0x20\n swap1\n dup2\n mstore\n 0x40\n dup1\n dup4\n sha3\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1374:1399 */\n swap4\n dup6\n and\n dup4\n mstore\n swap3\n swap1\n mstore\n sha3\n sload\n /* \"1.0.0/ERC20Token/ERC20Token_v1.sol\":1280:1406 */\n tag_56:\n swap3\n swap2\n pop\n pop\n jump\t// out\n}\n",
+ "bytecode": {
+ "linkReferences": {},
+ "object": "0x60606040526b033b2e3c9fd0803ce8000000600355341561001c57fe5b5b600354600160a060020a0333166000908152602081905260409020555b5b61078d8061004a6000396000f300606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058208999c5329f53064aac58d4b553cb379a45bfca17e024506ff916637cfc36f7b20029",
+ "opcodes": "PUSH1 0x60 PUSH1 0x40 MSTORE PUSH12 0x33B2E3C9FD0803CE8000000 PUSH1 0x3 SSTORE CALLVALUE ISZERO PUSH2 0x1C JUMPI INVALID JUMPDEST JUMPDEST PUSH1 0x3 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB CALLER AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SSTORE JUMPDEST JUMPDEST PUSH2 0x78D DUP1 PUSH2 0x4A PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0x96 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x6FDDE03 DUP2 EQ PUSH2 0x98 JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x146 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x186 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1A8 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x1EE JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x214 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x24F JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x2FD JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x33D JUMPI JUMPDEST INVALID JUMPDEST CALLVALUE ISZERO PUSH2 0xA0 JUMPI INVALID JUMPDEST PUSH2 0xA8 PUSH2 0x37E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 ADD SWAP1 DUP1 DUP4 DUP4 DUP3 ISZERO PUSH2 0x10C JUMPI JUMPDEST DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP4 GT ISZERO PUSH2 0x10C JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0xCE JUMP JUMPDEST POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x138 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x14E JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH1 0x24 CALLDATALOAD PUSH2 0x3B5 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x18E JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH2 0x42D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1B0 JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH1 0x44 CALLDATALOAD PUSH2 0x433 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1F6 JUMPI INVALID JUMPDEST PUSH2 0x1FE PUSH2 0x5D4 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x21C JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH2 0x5D9 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x257 JUMPI INVALID JUMPDEST PUSH2 0xA8 PUSH2 0x605 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 ADD SWAP1 DUP1 DUP4 DUP4 DUP3 ISZERO PUSH2 0x10C JUMPI JUMPDEST DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP4 GT ISZERO PUSH2 0x10C JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0xCE JUMP JUMPDEST POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x138 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x305 JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH1 0x24 CALLDATALOAD PUSH2 0x63C JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x345 JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x727 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x11 DUP2 MSTORE PUSH32 0x30782050726F746F636F6C20546F6B656E000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER DUP2 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 SWAP5 DUP8 AND DUP1 DUP5 MSTORE SWAP5 DUP3 MSTORE DUP1 DUP4 SHA3 DUP7 SWAP1 SSTORE DUP1 MLOAD DUP7 DUP2 MSTORE SWAP1 MLOAD SWAP3 SWAP5 SWAP4 SWAP3 PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 SWAP3 SWAP2 DUP2 SWAP1 SUB SWAP1 SWAP2 ADD SWAP1 LOG3 POP PUSH1 0x1 JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x3 SLOAD DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP5 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 CALLER SWAP1 SWAP6 AND DUP4 MSTORE SWAP4 DUP2 MSTORE DUP4 DUP3 SHA3 SLOAD SWAP3 DUP3 MSTORE DUP2 SWAP1 MSTORE SWAP2 DUP3 SHA3 SLOAD DUP4 SWAP1 LT DUP1 ISZERO SWAP1 PUSH2 0x483 JUMPI POP DUP3 DUP2 LT ISZERO JUMPDEST DUP1 ISZERO PUSH2 0x4B6 JUMPI POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP5 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD DUP4 DUP2 ADD LT ISZERO JUMPDEST ISZERO PUSH2 0x5C6 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP6 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP1 DUP3 SHA3 DUP1 SLOAD DUP8 ADD SWAP1 SSTORE SWAP2 DUP8 AND DUP2 MSTORE SHA3 DUP1 SLOAD DUP5 SWAP1 SUB SWAP1 SSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x558 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP7 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 CALLER SWAP1 SWAP5 AND DUP4 MSTORE SWAP3 SWAP1 MSTORE SHA3 DUP1 SLOAD DUP5 SWAP1 SUB SWAP1 SSTORE JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP PUSH2 0x5CB JUMP JUMPDEST PUSH1 0x0 SWAP2 POP JUMPDEST JUMPDEST POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x12 DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x5A52580000000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 SHA3 SLOAD DUP3 SWAP1 LT DUP1 ISZERO SWAP1 PUSH2 0x699 JUMPI POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD DUP3 DUP2 ADD LT ISZERO JUMPDEST ISZERO PUSH2 0x718 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER DUP2 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 DUP1 SLOAD DUP9 SWAP1 SUB SWAP1 SSTORE SWAP4 DUP8 AND DUP1 DUP4 MSTORE SWAP2 DUP5 SWAP1 SHA3 DUP1 SLOAD DUP8 ADD SWAP1 SSTORE DUP4 MLOAD DUP7 DUP2 MSTORE SWAP4 MLOAD SWAP2 SWAP4 PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF SWAP3 SWAP1 DUP2 SWAP1 SUB SWAP1 SWAP2 ADD SWAP1 LOG3 POP PUSH1 0x1 PUSH2 0x427 JUMP JUMPDEST POP PUSH1 0x0 PUSH2 0x427 JUMP JUMPDEST JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 SWAP4 DUP6 AND DUP4 MSTORE SWAP3 SWAP1 MSTORE SHA3 SLOAD JUMPDEST SWAP3 SWAP2 POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 SHA3 DUP10 SWAP10 0xc5 ORIGIN SWAP16 MSTORE8 MOD 0x4a 0xac PC 0xd4 0xb5 MSTORE8 0xcb CALLDATACOPY SWAP11 GASLIMIT 0xbf 0xca OR 0xe0 0x24 POP PUSH16 0xF916637CFC36F7B20029000000000000 ",
+ "sourceMap": "795:447:3:-;;;958:6;932:32;;1150:90;;;;;;;1222:11;;-1:-1:-1;;;;;1208:10:3;1199:20;:8;:20;;;;;;;;;;:34;1150:90;795:447;;;;;;;"
+ },
+ "deployedBytecode": {
+ "linkReferences": {},
+ "object": "0x606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058208999c5329f53064aac58d4b553cb379a45bfca17e024506ff916637cfc36f7b20029",
+ "opcodes": "PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0x96 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x6FDDE03 DUP2 EQ PUSH2 0x98 JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x146 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x186 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1A8 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x1EE JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x214 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x24F JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x2FD JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x33D JUMPI JUMPDEST INVALID JUMPDEST CALLVALUE ISZERO PUSH2 0xA0 JUMPI INVALID JUMPDEST PUSH2 0xA8 PUSH2 0x37E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 ADD SWAP1 DUP1 DUP4 DUP4 DUP3 ISZERO PUSH2 0x10C JUMPI JUMPDEST DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP4 GT ISZERO PUSH2 0x10C JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0xCE JUMP JUMPDEST POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x138 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x14E JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH1 0x24 CALLDATALOAD PUSH2 0x3B5 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x18E JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH2 0x42D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1B0 JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH1 0x44 CALLDATALOAD PUSH2 0x433 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1F6 JUMPI INVALID JUMPDEST PUSH2 0x1FE PUSH2 0x5D4 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x21C JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH2 0x5D9 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x257 JUMPI INVALID JUMPDEST PUSH2 0xA8 PUSH2 0x605 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 ADD SWAP1 DUP1 DUP4 DUP4 DUP3 ISZERO PUSH2 0x10C JUMPI JUMPDEST DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP4 GT ISZERO PUSH2 0x10C JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0xCE JUMP JUMPDEST POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x138 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x305 JUMPI INVALID JUMPDEST PUSH2 0x172 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD AND PUSH1 0x24 CALLDATALOAD PUSH2 0x63C JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x345 JUMPI INVALID JUMPDEST PUSH2 0x196 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x727 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x11 DUP2 MSTORE PUSH32 0x30782050726F746F636F6C20546F6B656E000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER DUP2 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 SWAP5 DUP8 AND DUP1 DUP5 MSTORE SWAP5 DUP3 MSTORE DUP1 DUP4 SHA3 DUP7 SWAP1 SSTORE DUP1 MLOAD DUP7 DUP2 MSTORE SWAP1 MLOAD SWAP3 SWAP5 SWAP4 SWAP3 PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 SWAP3 SWAP2 DUP2 SWAP1 SUB SWAP1 SWAP2 ADD SWAP1 LOG3 POP PUSH1 0x1 JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x3 SLOAD DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP5 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 CALLER SWAP1 SWAP6 AND DUP4 MSTORE SWAP4 DUP2 MSTORE DUP4 DUP3 SHA3 SLOAD SWAP3 DUP3 MSTORE DUP2 SWAP1 MSTORE SWAP2 DUP3 SHA3 SLOAD DUP4 SWAP1 LT DUP1 ISZERO SWAP1 PUSH2 0x483 JUMPI POP DUP3 DUP2 LT ISZERO JUMPDEST DUP1 ISZERO PUSH2 0x4B6 JUMPI POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP5 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD DUP4 DUP2 ADD LT ISZERO JUMPDEST ISZERO PUSH2 0x5C6 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP6 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP1 DUP3 SHA3 DUP1 SLOAD DUP8 ADD SWAP1 SSTORE SWAP2 DUP8 AND DUP2 MSTORE SHA3 DUP1 SLOAD DUP5 SWAP1 SUB SWAP1 SSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x558 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP7 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 CALLER SWAP1 SWAP5 AND DUP4 MSTORE SWAP3 SWAP1 MSTORE SHA3 DUP1 SLOAD DUP5 SWAP1 SUB SWAP1 SSTORE JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP PUSH2 0x5CB JUMP JUMPDEST PUSH1 0x0 SWAP2 POP JUMPDEST JUMPDEST POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x12 DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x5A52580000000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 SHA3 SLOAD DUP3 SWAP1 LT DUP1 ISZERO SWAP1 PUSH2 0x699 JUMPI POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 SHA3 SLOAD DUP3 DUP2 ADD LT ISZERO JUMPDEST ISZERO PUSH2 0x718 JUMPI PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CALLER DUP2 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 DUP1 SLOAD DUP9 SWAP1 SUB SWAP1 SSTORE SWAP4 DUP8 AND DUP1 DUP4 MSTORE SWAP2 DUP5 SWAP1 SHA3 DUP1 SLOAD DUP8 ADD SWAP1 SSTORE DUP4 MLOAD DUP7 DUP2 MSTORE SWAP4 MLOAD SWAP2 SWAP4 PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF SWAP3 SWAP1 DUP2 SWAP1 SUB SWAP1 SWAP2 ADD SWAP1 LOG3 POP PUSH1 0x1 PUSH2 0x427 JUMP JUMPDEST POP PUSH1 0x0 PUSH2 0x427 JUMP JUMPDEST JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP1 DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 SHA3 SWAP4 DUP6 AND DUP4 MSTORE SWAP3 SWAP1 MSTORE SHA3 SLOAD JUMPDEST SWAP3 SWAP2 POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 SHA3 DUP10 SWAP10 0xc5 ORIGIN SWAP16 MSTORE8 MOD 0x4a 0xac PC 0xd4 0xb5 MSTORE8 0xcb CALLDATACOPY SWAP11 GASLIMIT 0xbf 0xca OR 0xe0 0x24 POP PUSH16 0xF916637CFC36F7B20029000000000000 ",
+ "sourceMap": "795:447:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1009:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18:2:-1;;13:3;7:5;32;59:3;53:5;48:3;41:6;93:2;88:3;85:2;78:6;73:3;67:5;152:3;;;;;117:2;108:3;;;;130;172:5;167:4;181:3;3:186;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1087:187:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;932:32:3;;;;;;;;;;;;;;;;;;;;;;;;;;1066:609:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;891:35:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;982:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1064:37:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18:2:-1;;13:3;7:5;32;59:3;53:5;48:3;41:6;93:2;88:3;85:2;78:6;73:3;67:5;152:3;;;;;117:2;108:3;;;;130;172:5;167:4;181:3;3:186;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125:410:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1280:126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1009:49:3;;;;;;;;;;;;;;;;;;;:::o;1087:187:0:-;1160:19;1168:10;1160:19;;1144:4;1160:19;;;:7;:19;;;;;;;;:29;;;;;;;;;;;;:38;;;1208;;;;;;;1144:4;;1160:29;:19;1208:38;;;;;;;;;;;-1:-1:-1;1263:4:0;1087:187;;;;;:::o;932:32:3:-;;;;:::o;1066:609:2:-;1198:14;;;;1161:4;1198:14;;;:7;:14;;;;;;;;1213:10;1198:26;;;;;;;;;;;;1238:15;;;;;;;;;;:25;;;;;;:60;;;1292:6;1279:9;:19;;1238:60;:115;;;;-1:-1:-1;1340:13:2;;;:8;:13;;;;;;;;;;;1314:22;;;:39;;1238:115;1234:435;;;1378:13;;;;:8;:13;;;;;;;;;;;:23;;;;;;1415:15;;;;;;:25;;;;;;;768:10;1458:20;;1454:95;;;1498:14;;;;;;;;:7;:14;;;;;;;;1513:10;1498:26;;;;;;;;;:36;;;;;;;1454:95;1578:3;1562:28;;1571:5;1562:28;;;1583:6;1562:28;;;;;;;;;;;;;;;;;;1611:4;1604:11;;;;1234:435;1653:5;1646:12;;1234:435;1066:609;;;;;;;:::o;891:35:3:-;924:2;891:35;:::o;982:99:0:-;1058:16;;;1035:4;1058:16;;;;;;;;;;;982:99;;;;:::o;1064:37:3:-;;;;;;;;;;;;;;;;;;;:::o;125:410:0:-;267:20;276:10;267:20;178:4;267:20;;;;;;;;;;;:30;;;;;;:73;;-1:-1:-1;327:13:0;;;:8;:13;;;;;;;;;;;301:22;;;:39;;267:73;263:266;;;356:20;365:10;356:20;;:8;:20;;;;;;;;;;;:30;;;;;;;400:13;;;;;;;;;;:23;;;;;;437:33;;;;;;;400:13;;437:33;;;;;;;;;;;-1:-1:-1;491:4:0;484:11;;263:266;-1:-1:-1;521:5:0;514:12;;263:266;125:410;;;;;:::o;1280:126::-;1374:15;;;;1351:4;1374:15;;;:7;:15;;;;;;;;:25;;;;;;;;;;1280:126;;;;;:::o"
+ },
+ "gasEstimates": {
+ "creation": {
+ "codeDepositCost": "386600",
+ "executionCost": "40780",
+ "totalCost": "427380"
+ },
+ "external": {
+ "allowance(address,address)": "737",
+ "approve(address,uint256)": "22218",
+ "balanceOf(address)": "579",
+ "decimals()": "270",
+ "name()": "530",
+ "symbol()": "662",
+ "totalSupply()": "417",
+ "transfer(address,uint256)": "43393",
+ "transferFrom(address,address,uint256)": "64116"
+ }
+ },
+ "legacyAssembly": {
+ ".code": [
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "60"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 958,
+ "end": 964,
+ "name": "PUSH",
+ "value": "33B2E3C9FD0803CE8000000"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH",
+ "value": "3"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "PUSH [tag]",
+ "value": "1"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "tag",
+ "value": "1"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "tag",
+ "value": "2"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1222,
+ "end": 1233,
+ "name": "PUSH",
+ "value": "3"
+ },
+ {
+ "begin": 1222,
+ "end": 1233,
+ "name": "SLOAD"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "PUSH",
+ "value": "A0"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "PUSH",
+ "value": "2"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "EXP"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "SUB"
+ },
+ {
+ "begin": 1208,
+ "end": 1218,
+ "name": "CALLER"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "AND"
+ },
+ {
+ "begin": 1199,
+ "end": 1207,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1199,
+ "end": 1219,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1199,
+ "end": 1233,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "tag",
+ "value": "3"
+ },
+ {
+ "begin": 1150,
+ "end": 1240,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "tag",
+ "value": "4"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH #[$]",
+ "value": "0000000000000000000000000000000000000000000000000000000000000000"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [$]",
+ "value": "0000000000000000000000000000000000000000000000000000000000000000"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "CODECOPY"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "RETURN"
+ }
+ ],
+ ".data": {
+ "0": {
+ ".code": [
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "60"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "CALLDATASIZE"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "FFFFFFFF"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "100000000000000000000000000000000000000000000000000000000"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DIV"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "AND"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "6FDDE03"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP2"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "2"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "95EA7B3"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "3"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "18160DDD"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "4"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "23B872DD"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "5"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "313CE567"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "6"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "70A08231"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "7"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "95D89B41"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "8"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "A9059CBB"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "9"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "DUP1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH",
+ "value": "DD62ED3E"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "EQ"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "PUSH [tag]",
+ "value": "10"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "tag",
+ "value": "1"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 795,
+ "end": 1242,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "tag",
+ "value": "2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH [tag]",
+ "value": "11"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "tag",
+ "value": "11"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH [tag]",
+ "value": "12"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH [tag]",
+ "value": "13"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "tag",
+ "value": "12"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ADD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ADD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ADD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP4"
+ },
+ {
+ "begin": 18,
+ "end": 20,
+ "name": "DUP3"
+ },
+ {
+ "begin": 18,
+ "end": 20,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 13,
+ "end": 16,
+ "name": "PUSH [tag]",
+ "value": "14"
+ },
+ {
+ "begin": 7,
+ "end": 12,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 32,
+ "end": 37,
+ "name": "tag",
+ "value": "15"
+ },
+ {
+ "begin": 32,
+ "end": 37,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 59,
+ "end": 62,
+ "name": "DUP1"
+ },
+ {
+ "begin": 53,
+ "end": 58,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 48,
+ "end": 51,
+ "name": "DUP3"
+ },
+ {
+ "begin": 41,
+ "end": 47,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 93,
+ "end": 95,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 88,
+ "end": 91,
+ "name": "DUP4"
+ },
+ {
+ "begin": 85,
+ "end": 87,
+ "name": "GT"
+ },
+ {
+ "begin": 78,
+ "end": 84,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 73,
+ "end": 76,
+ "name": "PUSH [tag]",
+ "value": "14"
+ },
+ {
+ "begin": 67,
+ "end": 72,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "ADD"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 117,
+ "end": 119,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "DUP3"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "ADD"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 130,
+ "end": 133,
+ "name": "ADD"
+ },
+ {
+ "begin": 172,
+ "end": 177,
+ "name": "PUSH [tag]",
+ "value": "15"
+ },
+ {
+ "begin": 167,
+ "end": 171,
+ "name": "JUMP"
+ },
+ {
+ "begin": 181,
+ "end": 184,
+ "name": "tag",
+ "value": "14"
+ },
+ {
+ "begin": 181,
+ "end": 184,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ADD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "1F"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "AND"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH [tag]",
+ "value": "16"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP3"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP4"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "100"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "EXP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "NOT"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "AND"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ADD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "tag",
+ "value": "16"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "RETURN"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "tag",
+ "value": "3"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH [tag]",
+ "value": "17"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "tag",
+ "value": "17"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH [tag]",
+ "value": "18"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH",
+ "value": "4"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "AND"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH",
+ "value": "24"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH [tag]",
+ "value": "19"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "tag",
+ "value": "18"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SUB"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "ADD"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "RETURN"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "tag",
+ "value": "4"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH [tag]",
+ "value": "20"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "INVALID"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "tag",
+ "value": "20"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH [tag]",
+ "value": "21"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH [tag]",
+ "value": "22"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMP"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "tag",
+ "value": "21"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "DUP1"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "DUP3"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "DUP2"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SUB"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "ADD"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "RETURN"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "tag",
+ "value": "5"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH [tag]",
+ "value": "23"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "tag",
+ "value": "23"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH [tag]",
+ "value": "18"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "4"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "AND"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "24"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "AND"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "44"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH [tag]",
+ "value": "25"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "tag",
+ "value": "24"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SUB"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "ADD"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "RETURN"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "tag",
+ "value": "6"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH [tag]",
+ "value": "26"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "INVALID"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "tag",
+ "value": "26"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH [tag]",
+ "value": "27"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH [tag]",
+ "value": "28"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMP"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "tag",
+ "value": "27"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "DUP1"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH",
+ "value": "FF"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "AND"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "DUP3"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "DUP2"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SUB"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "ADD"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "RETURN"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "tag",
+ "value": "7"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH [tag]",
+ "value": "29"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "INVALID"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "tag",
+ "value": "29"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH [tag]",
+ "value": "21"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH",
+ "value": "4"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "AND"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH [tag]",
+ "value": "31"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMP"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "tag",
+ "value": "30"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "DUP1"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "DUP3"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "DUP2"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SUB"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "ADD"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "RETURN"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "tag",
+ "value": "8"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH [tag]",
+ "value": "32"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "tag",
+ "value": "32"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH [tag]",
+ "value": "12"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH [tag]",
+ "value": "34"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "tag",
+ "value": "33"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ADD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ADD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ADD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP4"
+ },
+ {
+ "begin": 18,
+ "end": 20,
+ "name": "DUP3"
+ },
+ {
+ "begin": 18,
+ "end": 20,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 13,
+ "end": 16,
+ "name": "PUSH [tag]",
+ "value": "14"
+ },
+ {
+ "begin": 7,
+ "end": 12,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 32,
+ "end": 37,
+ "name": "tag",
+ "value": "36"
+ },
+ {
+ "begin": 32,
+ "end": 37,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 59,
+ "end": 62,
+ "name": "DUP1"
+ },
+ {
+ "begin": 53,
+ "end": 58,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 48,
+ "end": 51,
+ "name": "DUP3"
+ },
+ {
+ "begin": 41,
+ "end": 47,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 93,
+ "end": 95,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 88,
+ "end": 91,
+ "name": "DUP4"
+ },
+ {
+ "begin": 85,
+ "end": 87,
+ "name": "GT"
+ },
+ {
+ "begin": 78,
+ "end": 84,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 73,
+ "end": 76,
+ "name": "PUSH [tag]",
+ "value": "14"
+ },
+ {
+ "begin": 67,
+ "end": 72,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "ADD"
+ },
+ {
+ "begin": 152,
+ "end": 155,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 117,
+ "end": 119,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "DUP3"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "ADD"
+ },
+ {
+ "begin": 108,
+ "end": 111,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 130,
+ "end": 133,
+ "name": "ADD"
+ },
+ {
+ "begin": 172,
+ "end": 177,
+ "name": "PUSH [tag]",
+ "value": "15"
+ },
+ {
+ "begin": 167,
+ "end": 171,
+ "name": "JUMP"
+ },
+ {
+ "begin": 181,
+ "end": 184,
+ "name": "tag",
+ "value": "35"
+ },
+ {
+ "begin": 181,
+ "end": 184,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ADD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "1F"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "AND"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH [tag]",
+ "value": "16"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP3"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP4"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "100"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "EXP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "NOT"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "AND"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "ADD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "tag",
+ "value": "37"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "POP"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SUB"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 3,
+ "end": 189,
+ "name": "RETURN"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "tag",
+ "value": "9"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH [tag]",
+ "value": "38"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "INVALID"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "tag",
+ "value": "38"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH [tag]",
+ "value": "18"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH",
+ "value": "4"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "AND"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH",
+ "value": "24"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH [tag]",
+ "value": "40"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMP"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "tag",
+ "value": "39"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "DUP1"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "DUP3"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "DUP2"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SUB"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "ADD"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "RETURN"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "tag",
+ "value": "10"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "CALLVALUE"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH [tag]",
+ "value": "41"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "INVALID"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "tag",
+ "value": "41"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH [tag]",
+ "value": "21"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH",
+ "value": "4"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "AND"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH",
+ "value": "24"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "CALLDATALOAD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "AND"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH [tag]",
+ "value": "43"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "tag",
+ "value": "42"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SUB"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "ADD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "RETURN"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "tag",
+ "value": "13"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ADD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "11"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "30782050726F746F636F6C20546F6B656E000000000000000000000000000000"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "ADD"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1009,
+ "end": 1058,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "tag",
+ "value": "19"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1168,
+ "end": 1178,
+ "name": "CALLER"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "AND"
+ },
+ {
+ "begin": 1144,
+ "end": 1148,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1160,
+ "end": 1167,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "SWAP5"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP8"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "AND"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP5"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "SWAP5"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1160,
+ "end": 1198,
+ "name": "DUP7"
+ },
+ {
+ "begin": 1160,
+ "end": 1198,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1160,
+ "end": 1198,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "DUP7"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1144,
+ "end": 1148,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1144,
+ "end": 1148,
+ "name": "SWAP5"
+ },
+ {
+ "begin": 1160,
+ "end": 1189,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 1160,
+ "end": 1179,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "PUSH",
+ "value": "8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SUB"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "ADD"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1208,
+ "end": 1246,
+ "name": "LOG3"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "POP"
+ },
+ {
+ "begin": 1263,
+ "end": 1267,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "tag",
+ "value": "44"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "POP"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "POP"
+ },
+ {
+ "begin": 1087,
+ "end": 1274,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "tag",
+ "value": "22"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "PUSH",
+ "value": "3"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "DUP2"
+ },
+ {
+ "begin": 932,
+ "end": 964,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "tag",
+ "value": "25"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP5"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "AND"
+ },
+ {
+ "begin": 1161,
+ "end": 1165,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1198,
+ "end": 1205,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1198,
+ "end": 1212,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1213,
+ "end": 1223,
+ "name": "CALLER"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "SWAP6"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "AND"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1198,
+ "end": 1224,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1238,
+ "end": 1253,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "LT"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1238,
+ "end": 1263,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1238,
+ "end": 1298,
+ "name": "PUSH [tag]",
+ "value": "46"
+ },
+ {
+ "begin": 1238,
+ "end": 1298,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1238,
+ "end": 1298,
+ "name": "POP"
+ },
+ {
+ "begin": 1292,
+ "end": 1298,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1279,
+ "end": 1288,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1279,
+ "end": 1298,
+ "name": "LT"
+ },
+ {
+ "begin": 1279,
+ "end": 1298,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1238,
+ "end": 1298,
+ "name": "tag",
+ "value": "46"
+ },
+ {
+ "begin": 1238,
+ "end": 1298,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "PUSH [tag]",
+ "value": "47"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "JUMPI"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "POP"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "DUP5"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "AND"
+ },
+ {
+ "begin": 1340,
+ "end": 1348,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1340,
+ "end": 1353,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1314,
+ "end": 1336,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1314,
+ "end": 1336,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1314,
+ "end": 1336,
+ "name": "ADD"
+ },
+ {
+ "begin": 1314,
+ "end": 1353,
+ "name": "LT"
+ },
+ {
+ "begin": 1314,
+ "end": 1353,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "tag",
+ "value": "47"
+ },
+ {
+ "begin": 1238,
+ "end": 1353,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "PUSH [tag]",
+ "value": "48"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "AND"
+ },
+ {
+ "begin": 1378,
+ "end": 1386,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1378,
+ "end": 1391,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "DUP8"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "ADD"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1378,
+ "end": 1401,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "DUP8"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "AND"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1415,
+ "end": 1430,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "DUP5"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "SUB"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1415,
+ "end": 1440,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 768,
+ "end": 778,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1458,
+ "end": 1478,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1458,
+ "end": 1478,
+ "name": "LT"
+ },
+ {
+ "begin": 1454,
+ "end": 1549,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 1454,
+ "end": 1549,
+ "name": "PUSH [tag]",
+ "value": "49"
+ },
+ {
+ "begin": 1454,
+ "end": 1549,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP7"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "AND"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1498,
+ "end": 1505,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1498,
+ "end": 1512,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1513,
+ "end": 1523,
+ "name": "CALLER"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "SWAP5"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "AND"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1498,
+ "end": 1524,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "DUP5"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "SUB"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1498,
+ "end": 1534,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 1454,
+ "end": 1549,
+ "name": "tag",
+ "value": "49"
+ },
+ {
+ "begin": 1454,
+ "end": 1549,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1578,
+ "end": 1581,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "AND"
+ },
+ {
+ "begin": 1571,
+ "end": 1576,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "AND"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "DDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF"
+ },
+ {
+ "begin": 1583,
+ "end": 1589,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "ADD"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "POP"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "POP"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "SUB"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1562,
+ "end": 1590,
+ "name": "LOG3"
+ },
+ {
+ "begin": 1611,
+ "end": 1615,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1604,
+ "end": 1615,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1604,
+ "end": 1615,
+ "name": "POP"
+ },
+ {
+ "begin": 1604,
+ "end": 1615,
+ "name": "PUSH [tag]",
+ "value": "50"
+ },
+ {
+ "begin": 1604,
+ "end": 1615,
+ "name": "JUMP"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "tag",
+ "value": "48"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1653,
+ "end": 1658,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1646,
+ "end": 1658,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1646,
+ "end": 1658,
+ "name": "POP"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "tag",
+ "value": "50"
+ },
+ {
+ "begin": 1234,
+ "end": 1669,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "tag",
+ "value": "45"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "POP"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "POP"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "POP"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "POP"
+ },
+ {
+ "begin": 1066,
+ "end": 1675,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "tag",
+ "value": "28"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 924,
+ "end": 926,
+ "name": "PUSH",
+ "value": "12"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "DUP2"
+ },
+ {
+ "begin": 891,
+ "end": 926,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "tag",
+ "value": "31"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "AND"
+ },
+ {
+ "begin": 1035,
+ "end": 1039,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1058,
+ "end": 1074,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "tag",
+ "value": "51"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "POP"
+ },
+ {
+ "begin": 982,
+ "end": 1081,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "tag",
+ "value": "34"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ADD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "5A52580000000000000000000000000000000000000000000000000000000000"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP3"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "ADD"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1064,
+ "end": 1101,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "tag",
+ "value": "40"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 276,
+ "end": 286,
+ "name": "CALLER"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "AND"
+ },
+ {
+ "begin": 178,
+ "end": 182,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "DUP2"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "DUP2"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "DUP2"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "SHA3"
+ },
+ {
+ "begin": 267,
+ "end": 287,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "DUP3"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "LT"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "DUP1"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 267,
+ "end": 297,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 267,
+ "end": 340,
+ "name": "PUSH [tag]",
+ "value": "53"
+ },
+ {
+ "begin": 267,
+ "end": 340,
+ "name": "JUMPI"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "POP"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "DUP4"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "AND"
+ },
+ {
+ "begin": 327,
+ "end": 335,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "DUP2"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "DUP2"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "SHA3"
+ },
+ {
+ "begin": 327,
+ "end": 340,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 301,
+ "end": 323,
+ "name": "DUP3"
+ },
+ {
+ "begin": 301,
+ "end": 323,
+ "name": "DUP2"
+ },
+ {
+ "begin": 301,
+ "end": 323,
+ "name": "ADD"
+ },
+ {
+ "begin": 301,
+ "end": 340,
+ "name": "LT"
+ },
+ {
+ "begin": 301,
+ "end": 340,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 267,
+ "end": 340,
+ "name": "tag",
+ "value": "53"
+ },
+ {
+ "begin": 267,
+ "end": 340,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "ISZERO"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "PUSH [tag]",
+ "value": "54"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "JUMPI"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 365,
+ "end": 375,
+ "name": "CALLER"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP2"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "AND"
+ },
+ {
+ "begin": 356,
+ "end": 364,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP2"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP2"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP2"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP2"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP1"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "DUP4"
+ },
+ {
+ "begin": 356,
+ "end": 376,
+ "name": "SHA3"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "DUP1"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "DUP9"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "SUB"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 356,
+ "end": 386,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "DUP8"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "AND"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "DUP1"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "DUP4"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "DUP5"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SHA3"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "DUP1"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "DUP8"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "ADD"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 400,
+ "end": 423,
+ "name": "SSTORE"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "DUP4"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "DUP7"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "DUP2"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "MLOAD"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 400,
+ "end": 413,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "PUSH",
+ "value": "DDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "DUP2"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SUB"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "ADD"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 437,
+ "end": 470,
+ "name": "LOG3"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "POP"
+ },
+ {
+ "begin": 491,
+ "end": 495,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 484,
+ "end": 495,
+ "name": "PUSH [tag]",
+ "value": "44"
+ },
+ {
+ "begin": 484,
+ "end": 495,
+ "name": "JUMP"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "tag",
+ "value": "54"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": -1,
+ "end": -1,
+ "name": "POP"
+ },
+ {
+ "begin": 521,
+ "end": 526,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 514,
+ "end": 526,
+ "name": "PUSH [tag]",
+ "value": "44"
+ },
+ {
+ "begin": 514,
+ "end": 526,
+ "name": "JUMP"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "tag",
+ "value": "55"
+ },
+ {
+ "begin": 263,
+ "end": 529,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "tag",
+ "value": "52"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "POP"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "POP"
+ },
+ {
+ "begin": 125,
+ "end": 535,
+ "name": "JUMP",
+ "value": "[out]"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "tag",
+ "value": "43"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "PUSH",
+ "value": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "AND"
+ },
+ {
+ "begin": 1351,
+ "end": 1355,
+ "name": "PUSH",
+ "value": "0"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1374,
+ "end": 1381,
+ "name": "PUSH",
+ "value": "1"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "PUSH",
+ "value": "20"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP2"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "PUSH",
+ "value": "40"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP1"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1374,
+ "end": 1389,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "SWAP4"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "DUP6"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "AND"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "DUP4"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "SWAP1"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "MSTORE"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "SHA3"
+ },
+ {
+ "begin": 1374,
+ "end": 1399,
+ "name": "SLOAD"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "tag",
+ "value": "56"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMPDEST"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP3"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "SWAP2"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "POP"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "POP"
+ },
+ {
+ "begin": 1280,
+ "end": 1406,
+ "name": "JUMP",
+ "value": "[out]"
+ }
+ ]
+ }
+ }
+ },
+ "methodIdentifiers": {
+ "allowance(address,address)": "dd62ed3e",
+ "approve(address,uint256)": "095ea7b3",
+ "balanceOf(address)": "70a08231",
+ "decimals()": "313ce567",
+ "name()": "06fdde03",
+ "symbol()": "95d89b41",
+ "totalSupply()": "18160ddd",
+ "transfer(address,uint256)": "a9059cbb",
+ "transferFrom(address,address,uint256)": "23b872dd"
+ }
+ },
+ "metadata": "{\"compiler\":{\"version\":\"0.4.11+commit.68ef5810\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"transferFrom(address,address,uint256)\":{\"details\":\"ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.\",\"params\":{\"_from\":\"Address to transfer from.\",\"_to\":\"Address to transfer to.\",\"_value\":\"Amount to transfer.\"},\"return\":\"Success of transfer.\"}}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"2.0.0/tokens/ZRXToken/ZRXToken.sol\":\"ZRXToken\"},\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"1.0.0/ERC20Token/ERC20Token_v1.sol\":{\"keccak256\":\"0x3d710b436c430d6fe49f64b091555405360d76da6454b93faa8e213eea34a96d\",\"urls\":[\"bzzr://d12710a563415ad98ff28ecb3aab0b68467b3d023e7c130c73ed9918ef86158e\"]},\"1.0.0/Token/Token_v1.sol\":{\"keccak256\":\"0x35a82bc7bc0994caa97f8ea44660b9b5e796acfe72705b5ff7ed8f2a3c47ff37\",\"urls\":[\"bzzr://a62ae857a4cf2e8948e36d02470c612ac1a5ac20ebe1c1b553ad1ed8becb634e\"]},\"1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\":{\"keccak256\":\"0x2e1f4b899081cedd8940a9cd0f0f7413264c883312ed0ba9c53885766fe0a1a5\",\"urls\":[\"bzzr://47c42a58e56ffe81e49c8aabd3c391f5fa807fea299b3a2178501e3669baeb52\"]},\"2.0.0/tokens/ZRXToken/ZRXToken.sol\":{\"keccak256\":\"0x9eeb623d48909b083c77688b13b610811c53e37622b3fcbaa23c01873230f5d6\",\"urls\":[\"bzzr://84f3b5c2653068092771d443281018ff2ee0543817426d0fb6f9037a3570e37f\"]}},\"version\":1}",
+ "userdoc": {
+ "methods": {}
+ }
+ },
+ "sources": {
+ "1.0.0/ERC20Token/ERC20Token_v1.sol": {
+ "id": 0,
+ "legacyAST": {
+ "children": [
+ {
+ "attributes": {
+ "literals": [
+ "solidity",
+ "^",
+ "0.4",
+ ".11"
+ ]
+ },
+ "id": 126,
+ "name": "PragmaDirective",
+ "src": "0:24:0"
+ },
+ {
+ "attributes": {
+ "file": "../Token/Token_v1.sol"
+ },
+ "id": 128,
+ "name": "ImportDirective",
+ "src": "26:58:0"
+ },
+ {
+ "attributes": {
+ "fullyImplemented": true,
+ "isLibrary": false,
+ "linearizedBaseContracts": [
+ 322,
+ 397
+ ],
+ "name": "ERC20Token_v1"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "Token"
+ },
+ "id": 129,
+ "name": "UserDefinedTypeName",
+ "src": "112:5:0"
+ }
+ ],
+ "id": 130,
+ "name": "InheritanceSpecifier",
+ "src": "112:5:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "transfer",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 131,
+ "name": "ElementaryTypeName",
+ "src": "143:7:0"
+ }
+ ],
+ "id": 132,
+ "name": "VariableDeclaration",
+ "src": "143:11:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 133,
+ "name": "ElementaryTypeName",
+ "src": "156:4:0"
+ }
+ ],
+ "id": 134,
+ "name": "VariableDeclaration",
+ "src": "156:11:0"
+ }
+ ],
+ "id": 135,
+ "name": "ParameterList",
+ "src": "142:26:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 136,
+ "name": "ElementaryTypeName",
+ "src": "178:4:0"
+ }
+ ],
+ "id": 137,
+ "name": "VariableDeclaration",
+ "src": "178:4:0"
+ }
+ ],
+ "id": 138,
+ "name": "ParameterList",
+ "src": "177:6:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "&&",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 139,
+ "name": "Identifier",
+ "src": "267:8:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 140,
+ "name": "Identifier",
+ "src": "276:3:0"
+ }
+ ],
+ "id": 141,
+ "name": "MemberAccess",
+ "src": "276:10:0"
+ }
+ ],
+ "id": 142,
+ "name": "IndexAccess",
+ "src": "267:20:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 143,
+ "name": "Identifier",
+ "src": "291:6:0"
+ }
+ ],
+ "id": 144,
+ "name": "BinaryOperation",
+ "src": "267:30:0"
+ },
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "+",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 145,
+ "name": "Identifier",
+ "src": "301:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 146,
+ "name": "Identifier",
+ "src": "310:3:0"
+ }
+ ],
+ "id": 147,
+ "name": "IndexAccess",
+ "src": "301:13:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 148,
+ "name": "Identifier",
+ "src": "317:6:0"
+ }
+ ],
+ "id": 149,
+ "name": "BinaryOperation",
+ "src": "301:22:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 150,
+ "name": "Identifier",
+ "src": "327:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 151,
+ "name": "Identifier",
+ "src": "336:3:0"
+ }
+ ],
+ "id": 152,
+ "name": "IndexAccess",
+ "src": "327:13:0"
+ }
+ ],
+ "id": 153,
+ "name": "BinaryOperation",
+ "src": "301:39:0"
+ }
+ ],
+ "id": 154,
+ "name": "BinaryOperation",
+ "src": "267:73:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "-=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 155,
+ "name": "Identifier",
+ "src": "356:8:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 156,
+ "name": "Identifier",
+ "src": "365:3:0"
+ }
+ ],
+ "id": 157,
+ "name": "MemberAccess",
+ "src": "365:10:0"
+ }
+ ],
+ "id": 158,
+ "name": "IndexAccess",
+ "src": "356:20:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 159,
+ "name": "Identifier",
+ "src": "380:6:0"
+ }
+ ],
+ "id": 160,
+ "name": "Assignment",
+ "src": "356:30:0"
+ }
+ ],
+ "id": 161,
+ "name": "ExpressionStatement",
+ "src": "356:30:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "+=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 162,
+ "name": "Identifier",
+ "src": "400:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 163,
+ "name": "Identifier",
+ "src": "409:3:0"
+ }
+ ],
+ "id": 164,
+ "name": "IndexAccess",
+ "src": "400:13:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 165,
+ "name": "Identifier",
+ "src": "417:6:0"
+ }
+ ],
+ "id": 166,
+ "name": "Assignment",
+ "src": "400:23:0"
+ }
+ ],
+ "id": 167,
+ "name": "ExpressionStatement",
+ "src": "400:23:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "tuple()",
+ "type_conversion": false
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "function (address,address,uint256) constant",
+ "value": "Transfer"
+ },
+ "id": 168,
+ "name": "Identifier",
+ "src": "437:8:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 169,
+ "name": "Identifier",
+ "src": "446:3:0"
+ }
+ ],
+ "id": 170,
+ "name": "MemberAccess",
+ "src": "446:10:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 171,
+ "name": "Identifier",
+ "src": "458:3:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 172,
+ "name": "Identifier",
+ "src": "463:6:0"
+ }
+ ],
+ "id": 173,
+ "name": "FunctionCall",
+ "src": "437:33:0"
+ }
+ ],
+ "id": 174,
+ "name": "ExpressionStatement",
+ "src": "437:33:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "74727565",
+ "subdenomination": null,
+ "token": "true",
+ "type": "bool",
+ "value": "true"
+ },
+ "id": 175,
+ "name": "Literal",
+ "src": "491:4:0"
+ }
+ ],
+ "id": 176,
+ "name": "Return",
+ "src": "484:11:0"
+ }
+ ],
+ "id": 177,
+ "name": "Block",
+ "src": "342:164:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "66616c7365",
+ "subdenomination": null,
+ "token": "false",
+ "type": "bool",
+ "value": "false"
+ },
+ "id": 178,
+ "name": "Literal",
+ "src": "521:5:0"
+ }
+ ],
+ "id": 179,
+ "name": "Return",
+ "src": "514:12:0"
+ }
+ ],
+ "id": 180,
+ "name": "Block",
+ "src": "512:17:0"
+ }
+ ],
+ "id": 181,
+ "name": "IfStatement",
+ "src": "263:266:0"
+ }
+ ],
+ "id": 182,
+ "name": "Block",
+ "src": "184:351:0"
+ }
+ ],
+ "id": 183,
+ "name": "FunctionDefinition",
+ "src": "125:410:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "transferFrom",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_from",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 184,
+ "name": "ElementaryTypeName",
+ "src": "563:7:0"
+ }
+ ],
+ "id": 185,
+ "name": "VariableDeclaration",
+ "src": "563:13:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 186,
+ "name": "ElementaryTypeName",
+ "src": "578:7:0"
+ }
+ ],
+ "id": 187,
+ "name": "VariableDeclaration",
+ "src": "578:11:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 188,
+ "name": "ElementaryTypeName",
+ "src": "591:4:0"
+ }
+ ],
+ "id": 189,
+ "name": "VariableDeclaration",
+ "src": "591:11:0"
+ }
+ ],
+ "id": 190,
+ "name": "ParameterList",
+ "src": "562:41:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 191,
+ "name": "ElementaryTypeName",
+ "src": "613:4:0"
+ }
+ ],
+ "id": 192,
+ "name": "VariableDeclaration",
+ "src": "613:4:0"
+ }
+ ],
+ "id": 193,
+ "name": "ParameterList",
+ "src": "612:6:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "&&",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "&&",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 194,
+ "name": "Identifier",
+ "src": "633:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 195,
+ "name": "Identifier",
+ "src": "642:5:0"
+ }
+ ],
+ "id": 196,
+ "name": "IndexAccess",
+ "src": "633:15:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 197,
+ "name": "Identifier",
+ "src": "652:6:0"
+ }
+ ],
+ "id": 198,
+ "name": "BinaryOperation",
+ "src": "633:25:0"
+ },
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 199,
+ "name": "Identifier",
+ "src": "662:7:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 200,
+ "name": "Identifier",
+ "src": "670:5:0"
+ }
+ ],
+ "id": 201,
+ "name": "IndexAccess",
+ "src": "662:14:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 202,
+ "name": "Identifier",
+ "src": "677:3:0"
+ }
+ ],
+ "id": 203,
+ "name": "MemberAccess",
+ "src": "677:10:0"
+ }
+ ],
+ "id": 204,
+ "name": "IndexAccess",
+ "src": "662:26:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 205,
+ "name": "Identifier",
+ "src": "692:6:0"
+ }
+ ],
+ "id": 206,
+ "name": "BinaryOperation",
+ "src": "662:36:0"
+ }
+ ],
+ "id": 207,
+ "name": "BinaryOperation",
+ "src": "633:65:0"
+ },
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "+",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 208,
+ "name": "Identifier",
+ "src": "702:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 209,
+ "name": "Identifier",
+ "src": "711:3:0"
+ }
+ ],
+ "id": 210,
+ "name": "IndexAccess",
+ "src": "702:13:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 211,
+ "name": "Identifier",
+ "src": "718:6:0"
+ }
+ ],
+ "id": 212,
+ "name": "BinaryOperation",
+ "src": "702:22:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 213,
+ "name": "Identifier",
+ "src": "728:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 214,
+ "name": "Identifier",
+ "src": "737:3:0"
+ }
+ ],
+ "id": 215,
+ "name": "IndexAccess",
+ "src": "728:13:0"
+ }
+ ],
+ "id": 216,
+ "name": "BinaryOperation",
+ "src": "702:39:0"
+ }
+ ],
+ "id": 217,
+ "name": "BinaryOperation",
+ "src": "633:108:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "+=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 218,
+ "name": "Identifier",
+ "src": "757:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 219,
+ "name": "Identifier",
+ "src": "766:3:0"
+ }
+ ],
+ "id": 220,
+ "name": "IndexAccess",
+ "src": "757:13:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 221,
+ "name": "Identifier",
+ "src": "774:6:0"
+ }
+ ],
+ "id": 222,
+ "name": "Assignment",
+ "src": "757:23:0"
+ }
+ ],
+ "id": 223,
+ "name": "ExpressionStatement",
+ "src": "757:23:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "-=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 224,
+ "name": "Identifier",
+ "src": "794:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 225,
+ "name": "Identifier",
+ "src": "803:5:0"
+ }
+ ],
+ "id": 226,
+ "name": "IndexAccess",
+ "src": "794:15:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 227,
+ "name": "Identifier",
+ "src": "813:6:0"
+ }
+ ],
+ "id": 228,
+ "name": "Assignment",
+ "src": "794:25:0"
+ }
+ ],
+ "id": 229,
+ "name": "ExpressionStatement",
+ "src": "794:25:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "-=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 230,
+ "name": "Identifier",
+ "src": "833:7:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 231,
+ "name": "Identifier",
+ "src": "841:5:0"
+ }
+ ],
+ "id": 234,
+ "name": "IndexAccess",
+ "src": "833:14:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 232,
+ "name": "Identifier",
+ "src": "848:3:0"
+ }
+ ],
+ "id": 233,
+ "name": "MemberAccess",
+ "src": "848:10:0"
+ }
+ ],
+ "id": 235,
+ "name": "IndexAccess",
+ "src": "833:26:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 236,
+ "name": "Identifier",
+ "src": "863:6:0"
+ }
+ ],
+ "id": 237,
+ "name": "Assignment",
+ "src": "833:36:0"
+ }
+ ],
+ "id": 238,
+ "name": "ExpressionStatement",
+ "src": "833:36:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "tuple()",
+ "type_conversion": false
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "function (address,address,uint256) constant",
+ "value": "Transfer"
+ },
+ "id": 239,
+ "name": "Identifier",
+ "src": "883:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 240,
+ "name": "Identifier",
+ "src": "892:5:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 241,
+ "name": "Identifier",
+ "src": "899:3:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 242,
+ "name": "Identifier",
+ "src": "904:6:0"
+ }
+ ],
+ "id": 243,
+ "name": "FunctionCall",
+ "src": "883:28:0"
+ }
+ ],
+ "id": 244,
+ "name": "ExpressionStatement",
+ "src": "883:28:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "74727565",
+ "subdenomination": null,
+ "token": "true",
+ "type": "bool",
+ "value": "true"
+ },
+ "id": 245,
+ "name": "Literal",
+ "src": "932:4:0"
+ }
+ ],
+ "id": 246,
+ "name": "Return",
+ "src": "925:11:0"
+ }
+ ],
+ "id": 247,
+ "name": "Block",
+ "src": "743:204:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "66616c7365",
+ "subdenomination": null,
+ "token": "false",
+ "type": "bool",
+ "value": "false"
+ },
+ "id": 248,
+ "name": "Literal",
+ "src": "962:5:0"
+ }
+ ],
+ "id": 249,
+ "name": "Return",
+ "src": "955:12:0"
+ }
+ ],
+ "id": 250,
+ "name": "Block",
+ "src": "953:17:0"
+ }
+ ],
+ "id": 251,
+ "name": "IfStatement",
+ "src": "629:341:0"
+ }
+ ],
+ "id": 252,
+ "name": "Block",
+ "src": "619:357:0"
+ }
+ ],
+ "id": 253,
+ "name": "FunctionDefinition",
+ "src": "541:435:0"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "balanceOf",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_owner",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 254,
+ "name": "ElementaryTypeName",
+ "src": "1001:7:0"
+ }
+ ],
+ "id": 255,
+ "name": "VariableDeclaration",
+ "src": "1001:14:0"
+ }
+ ],
+ "id": 256,
+ "name": "ParameterList",
+ "src": "1000:16:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 257,
+ "name": "ElementaryTypeName",
+ "src": "1035:4:0"
+ }
+ ],
+ "id": 258,
+ "name": "VariableDeclaration",
+ "src": "1035:4:0"
+ }
+ ],
+ "id": 259,
+ "name": "ParameterList",
+ "src": "1034:6:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 260,
+ "name": "Identifier",
+ "src": "1058:8:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_owner"
+ },
+ "id": 261,
+ "name": "Identifier",
+ "src": "1067:6:0"
+ }
+ ],
+ "id": 262,
+ "name": "IndexAccess",
+ "src": "1058:16:0"
+ }
+ ],
+ "id": 263,
+ "name": "Return",
+ "src": "1051:23:0"
+ }
+ ],
+ "id": 264,
+ "name": "Block",
+ "src": "1041:40:0"
+ }
+ ],
+ "id": 265,
+ "name": "FunctionDefinition",
+ "src": "982:99:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "approve",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_spender",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 266,
+ "name": "ElementaryTypeName",
+ "src": "1104:7:0"
+ }
+ ],
+ "id": 267,
+ "name": "VariableDeclaration",
+ "src": "1104:16:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 268,
+ "name": "ElementaryTypeName",
+ "src": "1122:4:0"
+ }
+ ],
+ "id": 269,
+ "name": "VariableDeclaration",
+ "src": "1122:11:0"
+ }
+ ],
+ "id": 270,
+ "name": "ParameterList",
+ "src": "1103:31:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 271,
+ "name": "ElementaryTypeName",
+ "src": "1144:4:0"
+ }
+ ],
+ "id": 272,
+ "name": "VariableDeclaration",
+ "src": "1144:4:0"
+ }
+ ],
+ "id": 273,
+ "name": "ParameterList",
+ "src": "1143:6:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 274,
+ "name": "Identifier",
+ "src": "1160:7:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 275,
+ "name": "Identifier",
+ "src": "1168:3:0"
+ }
+ ],
+ "id": 276,
+ "name": "MemberAccess",
+ "src": "1168:10:0"
+ }
+ ],
+ "id": 278,
+ "name": "IndexAccess",
+ "src": "1160:19:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_spender"
+ },
+ "id": 277,
+ "name": "Identifier",
+ "src": "1180:8:0"
+ }
+ ],
+ "id": 279,
+ "name": "IndexAccess",
+ "src": "1160:29:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 280,
+ "name": "Identifier",
+ "src": "1192:6:0"
+ }
+ ],
+ "id": 281,
+ "name": "Assignment",
+ "src": "1160:38:0"
+ }
+ ],
+ "id": 282,
+ "name": "ExpressionStatement",
+ "src": "1160:38:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "tuple()",
+ "type_conversion": false
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "function (address,address,uint256) constant",
+ "value": "Approval"
+ },
+ "id": 283,
+ "name": "Identifier",
+ "src": "1208:8:0"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 284,
+ "name": "Identifier",
+ "src": "1217:3:0"
+ }
+ ],
+ "id": 285,
+ "name": "MemberAccess",
+ "src": "1217:10:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_spender"
+ },
+ "id": 286,
+ "name": "Identifier",
+ "src": "1229:8:0"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 287,
+ "name": "Identifier",
+ "src": "1239:6:0"
+ }
+ ],
+ "id": 288,
+ "name": "FunctionCall",
+ "src": "1208:38:0"
+ }
+ ],
+ "id": 289,
+ "name": "ExpressionStatement",
+ "src": "1208:38:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "74727565",
+ "subdenomination": null,
+ "token": "true",
+ "type": "bool",
+ "value": "true"
+ },
+ "id": 290,
+ "name": "Literal",
+ "src": "1263:4:0"
+ }
+ ],
+ "id": 291,
+ "name": "Return",
+ "src": "1256:11:0"
+ }
+ ],
+ "id": 292,
+ "name": "Block",
+ "src": "1150:124:0"
+ }
+ ],
+ "id": 293,
+ "name": "FunctionDefinition",
+ "src": "1087:187:0"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "allowance",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_owner",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 294,
+ "name": "ElementaryTypeName",
+ "src": "1299:7:0"
+ }
+ ],
+ "id": 295,
+ "name": "VariableDeclaration",
+ "src": "1299:14:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_spender",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 296,
+ "name": "ElementaryTypeName",
+ "src": "1315:7:0"
+ }
+ ],
+ "id": 297,
+ "name": "VariableDeclaration",
+ "src": "1315:16:0"
+ }
+ ],
+ "id": 298,
+ "name": "ParameterList",
+ "src": "1298:34:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 299,
+ "name": "ElementaryTypeName",
+ "src": "1351:4:0"
+ }
+ ],
+ "id": 300,
+ "name": "VariableDeclaration",
+ "src": "1351:4:0"
+ }
+ ],
+ "id": 301,
+ "name": "ParameterList",
+ "src": "1350:6:0"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 302,
+ "name": "Identifier",
+ "src": "1374:7:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_owner"
+ },
+ "id": 303,
+ "name": "Identifier",
+ "src": "1382:6:0"
+ }
+ ],
+ "id": 304,
+ "name": "IndexAccess",
+ "src": "1374:15:0"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_spender"
+ },
+ "id": 305,
+ "name": "Identifier",
+ "src": "1390:8:0"
+ }
+ ],
+ "id": 306,
+ "name": "IndexAccess",
+ "src": "1374:25:0"
+ }
+ ],
+ "id": 307,
+ "name": "Return",
+ "src": "1367:32:0"
+ }
+ ],
+ "id": 308,
+ "name": "Block",
+ "src": "1357:49:0"
+ }
+ ],
+ "id": 309,
+ "name": "FunctionDefinition",
+ "src": "1280:126:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "balances",
+ "storageLocation": "default",
+ "type": "mapping(address => uint256)",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 310,
+ "name": "ElementaryTypeName",
+ "src": "1421:7:0"
+ },
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 311,
+ "name": "ElementaryTypeName",
+ "src": "1432:4:0"
+ }
+ ],
+ "id": 312,
+ "name": "Mapping",
+ "src": "1412:25:0"
+ }
+ ],
+ "id": 313,
+ "name": "VariableDeclaration",
+ "src": "1412:34:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "allowed",
+ "storageLocation": "default",
+ "type": "mapping(address => mapping(address => uint256))",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 314,
+ "name": "ElementaryTypeName",
+ "src": "1461:7:0"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 315,
+ "name": "ElementaryTypeName",
+ "src": "1481:7:0"
+ },
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 316,
+ "name": "ElementaryTypeName",
+ "src": "1492:4:0"
+ }
+ ],
+ "id": 317,
+ "name": "Mapping",
+ "src": "1472:25:0"
+ }
+ ],
+ "id": 318,
+ "name": "Mapping",
+ "src": "1452:46:0"
+ }
+ ],
+ "id": 319,
+ "name": "VariableDeclaration",
+ "src": "1452:54:0"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "totalSupply",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 320,
+ "name": "ElementaryTypeName",
+ "src": "1512:4:0"
+ }
+ ],
+ "id": 321,
+ "name": "VariableDeclaration",
+ "src": "1512:23:0"
+ }
+ ],
+ "id": 322,
+ "name": "ContractDefinition",
+ "src": "86:1452:0"
+ }
+ ],
+ "name": "SourceUnit"
+ }
+ },
+ "1.0.0/Token/Token_v1.sol": {
+ "id": 1,
+ "legacyAST": {
+ "children": [
+ {
+ "attributes": {
+ "literals": [
+ "solidity",
+ "^",
+ "0.4",
+ ".11"
+ ]
+ },
+ "id": 324,
+ "name": "PragmaDirective",
+ "src": "0:24:1"
+ },
+ {
+ "attributes": {
+ "fullyImplemented": true,
+ "isLibrary": false,
+ "linearizedBaseContracts": [
+ 397
+ ],
+ "name": "Token_v1"
+ },
+ "children": [
+ {
+ "attributes": {
+ "constant": true,
+ "name": "totalSupply",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [],
+ "id": 325,
+ "name": "ParameterList",
+ "src": "110:2:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "supply",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 326,
+ "name": "ElementaryTypeName",
+ "src": "131:4:1"
+ }
+ ],
+ "id": 327,
+ "name": "VariableDeclaration",
+ "src": "131:11:1"
+ }
+ ],
+ "id": 328,
+ "name": "ParameterList",
+ "src": "130:13:1"
+ },
+ {
+ "children": [],
+ "id": 329,
+ "name": "Block",
+ "src": "144:2:1"
+ }
+ ],
+ "id": 330,
+ "name": "FunctionDefinition",
+ "src": "90:56:1"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "balanceOf",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_owner",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 331,
+ "name": "ElementaryTypeName",
+ "src": "274:7:1"
+ }
+ ],
+ "id": 332,
+ "name": "VariableDeclaration",
+ "src": "274:14:1"
+ }
+ ],
+ "id": 333,
+ "name": "ParameterList",
+ "src": "273:16:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "balance",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 334,
+ "name": "ElementaryTypeName",
+ "src": "308:4:1"
+ }
+ ],
+ "id": 335,
+ "name": "VariableDeclaration",
+ "src": "308:12:1"
+ }
+ ],
+ "id": 336,
+ "name": "ParameterList",
+ "src": "307:14:1"
+ },
+ {
+ "children": [],
+ "id": 337,
+ "name": "Block",
+ "src": "322:2:1"
+ }
+ ],
+ "id": 338,
+ "name": "FunctionDefinition",
+ "src": "255:69:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "transfer",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 339,
+ "name": "ElementaryTypeName",
+ "src": "578:7:1"
+ }
+ ],
+ "id": 340,
+ "name": "VariableDeclaration",
+ "src": "578:11:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 341,
+ "name": "ElementaryTypeName",
+ "src": "591:4:1"
+ }
+ ],
+ "id": 342,
+ "name": "VariableDeclaration",
+ "src": "591:11:1"
+ }
+ ],
+ "id": 343,
+ "name": "ParameterList",
+ "src": "577:26:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "success",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 344,
+ "name": "ElementaryTypeName",
+ "src": "613:4:1"
+ }
+ ],
+ "id": 345,
+ "name": "VariableDeclaration",
+ "src": "613:12:1"
+ }
+ ],
+ "id": 346,
+ "name": "ParameterList",
+ "src": "612:14:1"
+ },
+ {
+ "children": [],
+ "id": 347,
+ "name": "Block",
+ "src": "627:2:1"
+ }
+ ],
+ "id": 348,
+ "name": "FunctionDefinition",
+ "src": "560:69:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "transferFrom",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_from",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 349,
+ "name": "ElementaryTypeName",
+ "src": "972:7:1"
+ }
+ ],
+ "id": 350,
+ "name": "VariableDeclaration",
+ "src": "972:13:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 351,
+ "name": "ElementaryTypeName",
+ "src": "987:7:1"
+ }
+ ],
+ "id": 352,
+ "name": "VariableDeclaration",
+ "src": "987:11:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 353,
+ "name": "ElementaryTypeName",
+ "src": "1000:4:1"
+ }
+ ],
+ "id": 354,
+ "name": "VariableDeclaration",
+ "src": "1000:11:1"
+ }
+ ],
+ "id": 355,
+ "name": "ParameterList",
+ "src": "971:41:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "success",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 356,
+ "name": "ElementaryTypeName",
+ "src": "1022:4:1"
+ }
+ ],
+ "id": 357,
+ "name": "VariableDeclaration",
+ "src": "1022:12:1"
+ }
+ ],
+ "id": 358,
+ "name": "ParameterList",
+ "src": "1021:14:1"
+ },
+ {
+ "children": [],
+ "id": 359,
+ "name": "Block",
+ "src": "1036:2:1"
+ }
+ ],
+ "id": 360,
+ "name": "FunctionDefinition",
+ "src": "950:88:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "approve",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_spender",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 361,
+ "name": "ElementaryTypeName",
+ "src": "1338:7:1"
+ }
+ ],
+ "id": 362,
+ "name": "VariableDeclaration",
+ "src": "1338:16:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 363,
+ "name": "ElementaryTypeName",
+ "src": "1356:4:1"
+ }
+ ],
+ "id": 364,
+ "name": "VariableDeclaration",
+ "src": "1356:11:1"
+ }
+ ],
+ "id": 365,
+ "name": "ParameterList",
+ "src": "1337:31:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "success",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 366,
+ "name": "ElementaryTypeName",
+ "src": "1378:4:1"
+ }
+ ],
+ "id": 367,
+ "name": "VariableDeclaration",
+ "src": "1378:12:1"
+ }
+ ],
+ "id": 368,
+ "name": "ParameterList",
+ "src": "1377:14:1"
+ },
+ {
+ "children": [],
+ "id": 369,
+ "name": "Block",
+ "src": "1392:2:1"
+ }
+ ],
+ "id": 370,
+ "name": "FunctionDefinition",
+ "src": "1321:73:1"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "allowance",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_owner",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 371,
+ "name": "ElementaryTypeName",
+ "src": "1621:7:1"
+ }
+ ],
+ "id": 372,
+ "name": "VariableDeclaration",
+ "src": "1621:14:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_spender",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 373,
+ "name": "ElementaryTypeName",
+ "src": "1637:7:1"
+ }
+ ],
+ "id": 374,
+ "name": "VariableDeclaration",
+ "src": "1637:16:1"
+ }
+ ],
+ "id": 375,
+ "name": "ParameterList",
+ "src": "1620:34:1"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "remaining",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 376,
+ "name": "ElementaryTypeName",
+ "src": "1673:4:1"
+ }
+ ],
+ "id": 377,
+ "name": "VariableDeclaration",
+ "src": "1673:14:1"
+ }
+ ],
+ "id": 378,
+ "name": "ParameterList",
+ "src": "1672:16:1"
+ },
+ {
+ "children": [],
+ "id": 379,
+ "name": "Block",
+ "src": "1689:2:1"
+ }
+ ],
+ "id": 380,
+ "name": "FunctionDefinition",
+ "src": "1602:89:1"
+ },
+ {
+ "attributes": {
+ "name": "Transfer"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": true,
+ "name": "_from",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 381,
+ "name": "ElementaryTypeName",
+ "src": "1712:7:1"
+ }
+ ],
+ "id": 382,
+ "name": "VariableDeclaration",
+ "src": "1712:21:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": true,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 383,
+ "name": "ElementaryTypeName",
+ "src": "1735:7:1"
+ }
+ ],
+ "id": 384,
+ "name": "VariableDeclaration",
+ "src": "1735:19:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 385,
+ "name": "ElementaryTypeName",
+ "src": "1756:4:1"
+ }
+ ],
+ "id": 386,
+ "name": "VariableDeclaration",
+ "src": "1756:11:1"
+ }
+ ],
+ "id": 387,
+ "name": "ParameterList",
+ "src": "1711:57:1"
+ }
+ ],
+ "id": 388,
+ "name": "EventDefinition",
+ "src": "1697:72:1"
+ },
+ {
+ "attributes": {
+ "name": "Approval"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": true,
+ "name": "_owner",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 389,
+ "name": "ElementaryTypeName",
+ "src": "1789:7:1"
+ }
+ ],
+ "id": 390,
+ "name": "VariableDeclaration",
+ "src": "1789:22:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": true,
+ "name": "_spender",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 391,
+ "name": "ElementaryTypeName",
+ "src": "1813:7:1"
+ }
+ ],
+ "id": 392,
+ "name": "VariableDeclaration",
+ "src": "1813:24:1"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "indexed": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 393,
+ "name": "ElementaryTypeName",
+ "src": "1839:4:1"
+ }
+ ],
+ "id": 394,
+ "name": "VariableDeclaration",
+ "src": "1839:11:1"
+ }
+ ],
+ "id": 395,
+ "name": "ParameterList",
+ "src": "1788:63:1"
+ }
+ ],
+ "id": 396,
+ "name": "EventDefinition",
+ "src": "1774:78:1"
+ }
+ ],
+ "id": 397,
+ "name": "ContractDefinition",
+ "src": "26:1828:1"
+ }
+ ],
+ "name": "SourceUnit"
+ }
+ },
+ "1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol": {
+ "id": 2,
+ "legacyAST": {
+ "children": [
+ {
+ "attributes": {
+ "literals": [
+ "solidity",
+ "^",
+ "0.4",
+ ".11"
+ ]
+ },
+ "id": 33,
+ "name": "PragmaDirective",
+ "src": "580:24:2"
+ },
+ {
+ "attributes": {
+ "file": "../ERC20Token/ERC20Token_v1.sol"
+ },
+ "id": 35,
+ "name": "ImportDirective",
+ "src": "606:78:2"
+ },
+ {
+ "attributes": {
+ "fullyImplemented": true,
+ "isLibrary": false,
+ "linearizedBaseContracts": [
+ 124,
+ 322,
+ 397
+ ],
+ "name": "UnlimitedAllowanceToken_v1"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "ERC20Token"
+ },
+ "id": 36,
+ "name": "UserDefinedTypeName",
+ "src": "725:10:2"
+ }
+ ],
+ "id": 37,
+ "name": "InheritanceSpecifier",
+ "src": "725:10:2"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "MAX_UINT",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 38,
+ "name": "ElementaryTypeName",
+ "src": "743:4:2"
+ },
+ {
+ "attributes": {
+ "operator": "-",
+ "type": "int_const 115792089237316195423570985008687907853269984665640564039457584007913129639935"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "**",
+ "type": "int_const 115792089237316195423570985008687907853269984665640564039457584007913129639936"
+ },
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "32",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 2",
+ "value": "2"
+ },
+ "id": 39,
+ "name": "Literal",
+ "src": "768:1:2"
+ },
+ {
+ "attributes": {
+ "hexvalue": "323536",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 256",
+ "value": "256"
+ },
+ "id": 40,
+ "name": "Literal",
+ "src": "771:3:2"
+ }
+ ],
+ "id": 41,
+ "name": "BinaryOperation",
+ "src": "768:6:2"
+ },
+ {
+ "attributes": {
+ "hexvalue": "31",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 1",
+ "value": "1"
+ },
+ "id": 42,
+ "name": "Literal",
+ "src": "777:1:2"
+ }
+ ],
+ "id": 43,
+ "name": "BinaryOperation",
+ "src": "768:10:2"
+ }
+ ],
+ "id": 44,
+ "name": "VariableDeclaration",
+ "src": "743:35:2"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "transferFrom",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_from",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 45,
+ "name": "ElementaryTypeName",
+ "src": "1088:7:2"
+ }
+ ],
+ "id": 46,
+ "name": "VariableDeclaration",
+ "src": "1088:13:2"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_to",
+ "storageLocation": "default",
+ "type": "address",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "address"
+ },
+ "id": 47,
+ "name": "ElementaryTypeName",
+ "src": "1103:7:2"
+ }
+ ],
+ "id": 48,
+ "name": "VariableDeclaration",
+ "src": "1103:11:2"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "_value",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 49,
+ "name": "ElementaryTypeName",
+ "src": "1116:4:2"
+ }
+ ],
+ "id": 50,
+ "name": "VariableDeclaration",
+ "src": "1116:11:2"
+ }
+ ],
+ "id": 51,
+ "name": "ParameterList",
+ "src": "1087:41:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "",
+ "storageLocation": "default",
+ "type": "bool",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "bool"
+ },
+ "id": 52,
+ "name": "ElementaryTypeName",
+ "src": "1161:4:2"
+ }
+ ],
+ "id": 53,
+ "name": "VariableDeclaration",
+ "src": "1161:4:2"
+ }
+ ],
+ "id": 54,
+ "name": "ParameterList",
+ "src": "1160:6:2"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "constant": false,
+ "name": "allowance",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "internal"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 55,
+ "name": "ElementaryTypeName",
+ "src": "1181:4:2"
+ }
+ ],
+ "id": 56,
+ "name": "VariableDeclaration",
+ "src": "1181:14:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 57,
+ "name": "Identifier",
+ "src": "1198:7:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 58,
+ "name": "Identifier",
+ "src": "1206:5:2"
+ }
+ ],
+ "id": 59,
+ "name": "IndexAccess",
+ "src": "1198:14:2"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 60,
+ "name": "Identifier",
+ "src": "1213:3:2"
+ }
+ ],
+ "id": 61,
+ "name": "MemberAccess",
+ "src": "1213:10:2"
+ }
+ ],
+ "id": 62,
+ "name": "IndexAccess",
+ "src": "1198:26:2"
+ }
+ ],
+ "id": 63,
+ "name": "VariableDeclarationStatement",
+ "src": "1181:43:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "&&",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "&&",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 64,
+ "name": "Identifier",
+ "src": "1238:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 65,
+ "name": "Identifier",
+ "src": "1247:5:2"
+ }
+ ],
+ "id": 66,
+ "name": "IndexAccess",
+ "src": "1238:15:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 67,
+ "name": "Identifier",
+ "src": "1257:6:2"
+ }
+ ],
+ "id": 68,
+ "name": "BinaryOperation",
+ "src": "1238:25:2"
+ },
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "allowance"
+ },
+ "id": 69,
+ "name": "Identifier",
+ "src": "1279:9:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 70,
+ "name": "Identifier",
+ "src": "1292:6:2"
+ }
+ ],
+ "id": 71,
+ "name": "BinaryOperation",
+ "src": "1279:19:2"
+ }
+ ],
+ "id": 72,
+ "name": "BinaryOperation",
+ "src": "1238:60:2"
+ },
+ {
+ "attributes": {
+ "operator": ">=",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "operator": "+",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 73,
+ "name": "Identifier",
+ "src": "1314:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 74,
+ "name": "Identifier",
+ "src": "1323:3:2"
+ }
+ ],
+ "id": 75,
+ "name": "IndexAccess",
+ "src": "1314:13:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 76,
+ "name": "Identifier",
+ "src": "1330:6:2"
+ }
+ ],
+ "id": 77,
+ "name": "BinaryOperation",
+ "src": "1314:22:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 78,
+ "name": "Identifier",
+ "src": "1340:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 79,
+ "name": "Identifier",
+ "src": "1349:3:2"
+ }
+ ],
+ "id": 80,
+ "name": "IndexAccess",
+ "src": "1340:13:2"
+ }
+ ],
+ "id": 81,
+ "name": "BinaryOperation",
+ "src": "1314:39:2"
+ }
+ ],
+ "id": 82,
+ "name": "BinaryOperation",
+ "src": "1238:115:2"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "+=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 83,
+ "name": "Identifier",
+ "src": "1378:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 84,
+ "name": "Identifier",
+ "src": "1387:3:2"
+ }
+ ],
+ "id": 85,
+ "name": "IndexAccess",
+ "src": "1378:13:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 86,
+ "name": "Identifier",
+ "src": "1395:6:2"
+ }
+ ],
+ "id": 87,
+ "name": "Assignment",
+ "src": "1378:23:2"
+ }
+ ],
+ "id": 88,
+ "name": "ExpressionStatement",
+ "src": "1378:23:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "-=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 89,
+ "name": "Identifier",
+ "src": "1415:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 90,
+ "name": "Identifier",
+ "src": "1424:5:2"
+ }
+ ],
+ "id": 91,
+ "name": "IndexAccess",
+ "src": "1415:15:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 92,
+ "name": "Identifier",
+ "src": "1434:6:2"
+ }
+ ],
+ "id": 93,
+ "name": "Assignment",
+ "src": "1415:25:2"
+ }
+ ],
+ "id": 94,
+ "name": "ExpressionStatement",
+ "src": "1415:25:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "<",
+ "type": "bool"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "allowance"
+ },
+ "id": 95,
+ "name": "Identifier",
+ "src": "1458:9:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "MAX_UINT"
+ },
+ "id": 96,
+ "name": "Identifier",
+ "src": "1470:8:2"
+ }
+ ],
+ "id": 97,
+ "name": "BinaryOperation",
+ "src": "1458:20:2"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "-=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => mapping(address => uint256))",
+ "value": "allowed"
+ },
+ "id": 98,
+ "name": "Identifier",
+ "src": "1498:7:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 99,
+ "name": "Identifier",
+ "src": "1506:5:2"
+ }
+ ],
+ "id": 102,
+ "name": "IndexAccess",
+ "src": "1498:14:2"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 100,
+ "name": "Identifier",
+ "src": "1513:3:2"
+ }
+ ],
+ "id": 101,
+ "name": "MemberAccess",
+ "src": "1513:10:2"
+ }
+ ],
+ "id": 103,
+ "name": "IndexAccess",
+ "src": "1498:26:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 104,
+ "name": "Identifier",
+ "src": "1528:6:2"
+ }
+ ],
+ "id": 105,
+ "name": "Assignment",
+ "src": "1498:36:2"
+ }
+ ],
+ "id": 106,
+ "name": "ExpressionStatement",
+ "src": "1498:36:2"
+ }
+ ],
+ "id": 107,
+ "name": "Block",
+ "src": "1480:69:2"
+ }
+ ],
+ "id": 108,
+ "name": "IfStatement",
+ "src": "1454:95:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "type": "tuple()",
+ "type_conversion": false
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "function (address,address,uint256) constant",
+ "value": "Transfer"
+ },
+ "id": 109,
+ "name": "Identifier",
+ "src": "1562:8:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_from"
+ },
+ "id": 110,
+ "name": "Identifier",
+ "src": "1571:5:2"
+ },
+ {
+ "attributes": {
+ "type": "address",
+ "value": "_to"
+ },
+ "id": 111,
+ "name": "Identifier",
+ "src": "1578:3:2"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "_value"
+ },
+ "id": 112,
+ "name": "Identifier",
+ "src": "1583:6:2"
+ }
+ ],
+ "id": 113,
+ "name": "FunctionCall",
+ "src": "1562:28:2"
+ }
+ ],
+ "id": 114,
+ "name": "ExpressionStatement",
+ "src": "1562:28:2"
+ },
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "74727565",
+ "subdenomination": null,
+ "token": "true",
+ "type": "bool",
+ "value": "true"
+ },
+ "id": 115,
+ "name": "Literal",
+ "src": "1611:4:2"
+ }
+ ],
+ "id": 116,
+ "name": "Return",
+ "src": "1604:11:2"
+ }
+ ],
+ "id": 117,
+ "name": "Block",
+ "src": "1364:262:2"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "66616c7365",
+ "subdenomination": null,
+ "token": "false",
+ "type": "bool",
+ "value": "false"
+ },
+ "id": 118,
+ "name": "Literal",
+ "src": "1653:5:2"
+ }
+ ],
+ "id": 119,
+ "name": "Return",
+ "src": "1646:12:2"
+ }
+ ],
+ "id": 120,
+ "name": "Block",
+ "src": "1632:37:2"
+ }
+ ],
+ "id": 121,
+ "name": "IfStatement",
+ "src": "1234:435:2"
+ }
+ ],
+ "id": 122,
+ "name": "Block",
+ "src": "1171:504:2"
+ }
+ ],
+ "id": 123,
+ "name": "FunctionDefinition",
+ "src": "1066:609:2"
+ }
+ ],
+ "id": 124,
+ "name": "ContractDefinition",
+ "src": "686:991:2"
+ }
+ ],
+ "name": "SourceUnit"
+ }
+ },
+ "2.0.0/tokens/ZRXToken/ZRXToken.sol": {
+ "id": 3,
+ "legacyAST": {
+ "children": [
+ {
+ "attributes": {
+ "literals": [
+ "solidity",
+ "0.4",
+ ".11"
+ ]
+ },
+ "id": 1,
+ "name": "PragmaDirective",
+ "src": "580:23:3"
+ },
+ {
+ "attributes": {
+ "file": "../../../1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol"
+ },
+ "id": 3,
+ "name": "ImportDirective",
+ "src": "650:142:3"
+ },
+ {
+ "attributes": {
+ "fullyImplemented": true,
+ "isLibrary": false,
+ "linearizedBaseContracts": [
+ 31,
+ 124,
+ 322,
+ 397
+ ],
+ "name": "ZRXToken"
+ },
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "name": "UnlimitedAllowanceToken"
+ },
+ "id": 4,
+ "name": "UserDefinedTypeName",
+ "src": "816:23:3"
+ }
+ ],
+ "id": 5,
+ "name": "InheritanceSpecifier",
+ "src": "816:23:3"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "decimals",
+ "storageLocation": "default",
+ "type": "uint8",
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint8"
+ },
+ "id": 6,
+ "name": "ElementaryTypeName",
+ "src": "891:5:3"
+ },
+ {
+ "attributes": {
+ "hexvalue": "3138",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 18",
+ "value": "18"
+ },
+ "id": 7,
+ "name": "Literal",
+ "src": "924:2:3"
+ }
+ ],
+ "id": 8,
+ "name": "VariableDeclaration",
+ "src": "891:35:3"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "totalSupply",
+ "storageLocation": "default",
+ "type": "uint256",
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "uint"
+ },
+ "id": 9,
+ "name": "ElementaryTypeName",
+ "src": "932:4:3"
+ },
+ {
+ "attributes": {
+ "operator": "**",
+ "type": "int_const 1000000000000000000000000000"
+ },
+ "children": [
+ {
+ "attributes": {
+ "hexvalue": "3130",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 10",
+ "value": "10"
+ },
+ "id": 10,
+ "name": "Literal",
+ "src": "958:2:3"
+ },
+ {
+ "attributes": {
+ "hexvalue": "3237",
+ "subdenomination": null,
+ "token": null,
+ "type": "int_const 27",
+ "value": "27"
+ },
+ "id": 11,
+ "name": "Literal",
+ "src": "962:2:3"
+ }
+ ],
+ "id": 12,
+ "name": "BinaryOperation",
+ "src": "958:6:3"
+ }
+ ],
+ "id": 13,
+ "name": "VariableDeclaration",
+ "src": "932:32:3"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "name",
+ "storageLocation": "default",
+ "type": "string memory",
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "string"
+ },
+ "id": 14,
+ "name": "ElementaryTypeName",
+ "src": "1009:6:3"
+ },
+ {
+ "attributes": {
+ "hexvalue": "30782050726f746f636f6c20546f6b656e",
+ "subdenomination": null,
+ "token": null,
+ "type": "literal_string \"0x Protocol Token\"",
+ "value": "0x Protocol Token"
+ },
+ "id": 15,
+ "name": "Literal",
+ "src": "1039:19:3"
+ }
+ ],
+ "id": 16,
+ "name": "VariableDeclaration",
+ "src": "1009:49:3"
+ },
+ {
+ "attributes": {
+ "constant": true,
+ "name": "symbol",
+ "storageLocation": "default",
+ "type": "string memory",
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "attributes": {
+ "name": "string"
+ },
+ "id": 17,
+ "name": "ElementaryTypeName",
+ "src": "1064:6:3"
+ },
+ {
+ "attributes": {
+ "hexvalue": "5a5258",
+ "subdenomination": null,
+ "token": null,
+ "type": "literal_string \"ZRX\"",
+ "value": "ZRX"
+ },
+ "id": 18,
+ "name": "Literal",
+ "src": "1096:5:3"
+ }
+ ],
+ "id": 19,
+ "name": "VariableDeclaration",
+ "src": "1064:37:3"
+ },
+ {
+ "attributes": {
+ "constant": false,
+ "name": "ZRXToken",
+ "payable": false,
+ "visibility": "public"
+ },
+ "children": [
+ {
+ "children": [],
+ "id": 20,
+ "name": "ParameterList",
+ "src": "1167:2:3"
+ },
+ {
+ "children": [],
+ "id": 21,
+ "name": "ParameterList",
+ "src": "1189:0:3"
+ },
+ {
+ "children": [
+ {
+ "children": [
+ {
+ "attributes": {
+ "operator": "=",
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "uint256"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "mapping(address => uint256)",
+ "value": "balances"
+ },
+ "id": 22,
+ "name": "Identifier",
+ "src": "1199:8:3"
+ },
+ {
+ "attributes": {
+ "member_name": "sender",
+ "type": "address"
+ },
+ "children": [
+ {
+ "attributes": {
+ "type": "msg",
+ "value": "msg"
+ },
+ "id": 23,
+ "name": "Identifier",
+ "src": "1208:3:3"
+ }
+ ],
+ "id": 24,
+ "name": "MemberAccess",
+ "src": "1208:10:3"
+ }
+ ],
+ "id": 25,
+ "name": "IndexAccess",
+ "src": "1199:20:3"
+ },
+ {
+ "attributes": {
+ "type": "uint256",
+ "value": "totalSupply"
+ },
+ "id": 26,
+ "name": "Identifier",
+ "src": "1222:11:3"
+ }
+ ],
+ "id": 27,
+ "name": "Assignment",
+ "src": "1199:34:3"
+ }
+ ],
+ "id": 28,
+ "name": "ExpressionStatement",
+ "src": "1199:34:3"
+ }
+ ],
+ "id": 29,
+ "name": "Block",
+ "src": "1189:51:3"
+ }
+ ],
+ "id": 30,
+ "name": "FunctionDefinition",
+ "src": "1150:90:3"
+ }
+ ],
+ "id": 31,
+ "name": "ContractDefinition",
+ "src": "795:447:3"
+ }
+ ],
+ "name": "SourceUnit"
+ }
+ }
+ },
+ "sourceCodes": {
+ "1.0.0/ERC20Token/ERC20Token_v1.sol": "pragma solidity ^0.4.11;\n\nimport { Token_v1 as Token } from \"../Token/Token_v1.sol\";\n\ncontract ERC20Token_v1 is Token {\n\n function transfer(address _to, uint _value) returns (bool) {\n //Default assumes totalSupply can't be over max (2^256 - 1).\n if (balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]) {\n balances[msg.sender] -= _value;\n balances[_to] += _value;\n Transfer(msg.sender, _to, _value);\n return true;\n } else { return false; }\n }\n\n function transferFrom(address _from, address _to, uint _value) returns (bool) {\n if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]) {\n balances[_to] += _value;\n balances[_from] -= _value;\n allowed[_from][msg.sender] -= _value;\n Transfer(_from, _to, _value);\n return true;\n } else { return false; }\n }\n\n function balanceOf(address _owner) constant returns (uint) {\n return balances[_owner];\n }\n\n function approve(address _spender, uint _value) returns (bool) {\n allowed[msg.sender][_spender] = _value;\n Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function allowance(address _owner, address _spender) constant returns (uint) {\n return allowed[_owner][_spender];\n }\n\n mapping (address => uint) balances;\n mapping (address => mapping (address => uint)) allowed;\n uint public totalSupply;\n}\n",
+ "1.0.0/Token/Token_v1.sol": "pragma solidity ^0.4.11;\n\ncontract Token_v1 {\n\n /// @return total amount of tokens\n function totalSupply() constant returns (uint supply) {}\n\n /// @param _owner The address from which the balance will be retrieved\n /// @return The balance\n function balanceOf(address _owner) constant returns (uint balance) {}\n\n /// @notice send `_value` token to `_to` from `msg.sender`\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transfer(address _to, uint _value) returns (bool success) {}\n\n /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`\n /// @param _from The address of the sender\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transferFrom(address _from, address _to, uint _value) returns (bool success) {}\n\n /// @notice `msg.sender` approves `_addr` to spend `_value` tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @param _value The amount of wei to be approved for transfer\n /// @return Whether the approval was successful or not\n function approve(address _spender, uint _value) returns (bool success) {}\n\n /// @param _owner The address of the account owning tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @return Amount of remaining tokens allowed to spent\n function allowance(address _owner, address _spender) constant returns (uint remaining) {}\n\n event Transfer(address indexed _from, address indexed _to, uint _value);\n event Approval(address indexed _owner, address indexed _spender, uint _value);\n}\n\n",
+ "1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.11;\n\nimport { ERC20Token_v1 as ERC20Token } from \"../ERC20Token/ERC20Token_v1.sol\";\n\ncontract UnlimitedAllowanceToken_v1 is ERC20Token {\n\n uint constant MAX_UINT = 2**256 - 1;\n\n /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.\n /// @param _from Address to transfer from.\n /// @param _to Address to transfer to.\n /// @param _value Amount to transfer.\n /// @return Success of transfer.\n function transferFrom(address _from, address _to, uint _value)\n public\n returns (bool)\n {\n uint allowance = allowed[_from][msg.sender];\n if (balances[_from] >= _value\n && allowance >= _value\n && balances[_to] + _value >= balances[_to]\n ) {\n balances[_to] += _value;\n balances[_from] -= _value;\n if (allowance < MAX_UINT) {\n allowed[_from][msg.sender] -= _value;\n }\n Transfer(_from, _to, _value);\n return true;\n } else {\n return false;\n }\n }\n}\n",
+ "2.0.0/tokens/ZRXToken/ZRXToken.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.11;\n\n// solhint-disable-next-line max-line-length\nimport { UnlimitedAllowanceToken_v1 as UnlimitedAllowanceToken } from \"../../../1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol\";\n\n\ncontract ZRXToken is UnlimitedAllowanceToken {\n\n // solhint-disable const-name-snakecase\n uint8 constant public decimals = 18;\n uint public totalSupply = 10**27; // 1 billion tokens, 18 decimal places\n string constant public name = \"0x Protocol Token\";\n string constant public symbol = \"ZRX\";\n // solhint-enableconst-name-snakecase\n\n function ZRXToken()\n public\n {\n balances[msg.sender] = totalSupply;\n }\n}\n"
+ },
+ "sourceTreeHashHex": "0xbcce67d129fe53ddb9717b4f567b33108c41a4f4324aa47ac609037e41f5b95d",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.4.11+commit.68ef5810.js",
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode.object",
+ "evm.bytecode.sourceMap",
+ "evm.deployedBytecode.object",
+ "evm.deployedBytecode.sourceMap"
+ ]
+ }
+ }
+ }
+ },
+ "networks": {
+ "50": {
+ "address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c",
+ "links": {},
+ "constructorArgs": "[]"
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts b/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
deleted file mode 100644
index 6c96428ed..000000000
--- a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from '@0xproject/types';
-import { AbiDecoder, intervalUtils } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
-import * as _ from 'lodash';
-import * as Web3 from 'web3';
-
-import {
- Artifact,
- BlockRange,
- ContractEventArgs,
- ContractEvents,
- EventCallback,
- IndexedFilterValues,
- InternalZeroExError,
- ZeroExError,
-} from '../types';
-import { constants } from '../utils/constants';
-import { filterUtils } from '../utils/filter_utils';
-
-const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {
- [contractName: string]: ZeroExError;
-} = {
- ZRX: ZeroExError.ZRXContractDoesNotExist,
- EtherToken: ZeroExError.EtherTokenContractDoesNotExist,
- Token: ZeroExError.TokenContractDoesNotExist,
- TokenRegistry: ZeroExError.TokenRegistryContractDoesNotExist,
- TokenTransferProxy: ZeroExError.TokenTransferProxyContractDoesNotExist,
- Exchange: ZeroExError.ExchangeContractDoesNotExist,
-};
-
-export class ContractWrapper {
- protected _web3Wrapper: Web3Wrapper;
- protected _networkId: number;
- private _abiDecoder?: AbiDecoder;
- private _blockAndLogStreamerIfExists?: BlockAndLogStreamer;
- private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
- private _filters: { [filterToken: string]: FilterObject };
- private _filterCallbacks: {
- [filterToken: string]: EventCallback<ContractEventArgs>;
- };
- private _onLogAddedSubscriptionToken: string | undefined;
- private _onLogRemovedSubscriptionToken: string | undefined;
- constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder?: AbiDecoder) {
- this._web3Wrapper = web3Wrapper;
- this._networkId = networkId;
- this._abiDecoder = abiDecoder;
- this._filters = {};
- this._filterCallbacks = {};
- this._blockAndLogStreamerIfExists = undefined;
- this._onLogAddedSubscriptionToken = undefined;
- this._onLogRemovedSubscriptionToken = undefined;
- }
- protected _unsubscribeAll(): void {
- const filterTokens = _.keys(this._filterCallbacks);
- _.each(filterTokens, filterToken => {
- this._unsubscribe(filterToken);
- });
- }
- protected _unsubscribe(filterToken: string, err?: Error): void {
- if (_.isUndefined(this._filters[filterToken])) {
- throw new Error(ZeroExError.SubscriptionNotFound);
- }
- if (!_.isUndefined(err)) {
- const callback = this._filterCallbacks[filterToken];
- callback(err, undefined);
- }
- delete this._filters[filterToken];
- delete this._filterCallbacks[filterToken];
- if (_.isEmpty(this._filters)) {
- this._stopBlockAndLogStream();
- }
- }
- protected _subscribe<ArgsType extends ContractEventArgs>(
- address: string,
- eventName: ContractEvents,
- indexFilterValues: IndexedFilterValues,
- abi: ContractAbi,
- callback: EventCallback<ArgsType>,
- ): string {
- const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
- if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
- this._startBlockAndLogStream();
- }
- const filterToken = filterUtils.generateUUID();
- this._filters[filterToken] = filter;
- this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>;
- return filterToken;
- }
- protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
- address: string,
- eventName: ContractEvents,
- blockRange: BlockRange,
- indexFilterValues: IndexedFilterValues,
- abi: ContractAbi,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
- const logs = await this._web3Wrapper.getLogsAsync(filter);
- const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
- return logsWithDecodedArguments;
- }
- protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
- log: LogEntry,
- ): LogWithDecodedArgs<ArgsType> | RawLog {
- if (_.isUndefined(this._abiDecoder)) {
- throw new Error(InternalZeroExError.NoAbiDecoder);
- }
- const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
- return logWithDecodedArgs;
- }
- protected async _getContractAbiAndAddressFromArtifactsAsync(
- artifact: Artifact,
- addressIfExists?: string,
- ): Promise<[ContractAbi, string]> {
- let contractAddress: string;
- if (_.isUndefined(addressIfExists)) {
- if (_.isUndefined(artifact.networks[this._networkId])) {
- throw new Error(ZeroExError.ContractNotDeployedOnNetwork);
- }
- contractAddress = artifact.networks[this._networkId].address.toLowerCase();
- } else {
- contractAddress = addressIfExists;
- }
- const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress);
- if (!doesContractExist) {
- throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
- }
- const abiAndAddress: [ContractAbi, string] = [artifact.abi, contractAddress];
- return abiAndAddress;
- }
- protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
- if (_.isUndefined(addressIfExists)) {
- const contractAddress = artifact.networks[this._networkId].address;
- if (_.isUndefined(contractAddress)) {
- throw new Error(ZeroExError.ExchangeContractDoesNotExist);
- }
- return contractAddress;
- } else {
- return addressIfExists;
- }
- }
- private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: LogEntry): void {
- _.forEach(this._filters, (filter: FilterObject, filterToken: string) => {
- if (filterUtils.matchesFilter(log, filter)) {
- const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
- const logEvent = {
- log: decodedLog,
- isRemoved,
- };
- this._filterCallbacks[filterToken](null, logEvent);
- }
- });
- }
- private _startBlockAndLogStream(): void {
- if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
- throw new Error(ZeroExError.SubscriptionAlreadyPresent);
- }
- this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
- this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
- this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
- );
- const catchAllLogFilter = {};
- this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
- this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
- this._reconcileBlockAsync.bind(this),
- constants.DEFAULT_BLOCK_POLLING_INTERVAL,
- this._onReconcileBlockError.bind(this),
- );
- let isRemoved = false;
- this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
- this._onLogStateChanged.bind(this, isRemoved),
- );
- isRemoved = true;
- this._onLogRemovedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogRemoved(
- this._onLogStateChanged.bind(this, isRemoved),
- );
- }
- private _onReconcileBlockError(err: Error): void {
- const filterTokens = _.keys(this._filterCallbacks);
- _.each(filterTokens, filterToken => {
- this._unsubscribe(filterToken, err);
- });
- }
- private _setNetworkId(networkId: number): void {
- this._networkId = networkId;
- }
- private _stopBlockAndLogStream(): void {
- if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
- throw new Error(ZeroExError.SubscriptionNotFound);
- }
- this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
- this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);
- intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamIntervalIfExists as NodeJS.Timer);
- delete this._blockAndLogStreamerIfExists;
- }
- private async _reconcileBlockAsync(): Promise<void> {
- const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
- // We need to coerce to Block type cause Web3.Block includes types for mempool blocks
- if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
- // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
- await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
- }
- }
-}
diff --git a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts b/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts
deleted file mode 100644
index 4a4da116b..000000000
--- a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import { schemas } from '@0xproject/json-schemas';
-import { LogWithDecodedArgs } from '@0xproject/types';
-import { AbiDecoder, BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { artifacts } from '../artifacts';
-import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types';
-import { assert } from '../utils/assert';
-
-import { ContractWrapper } from './contract_wrapper';
-import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
-import { TokenWrapper } from './token_wrapper';
-
-/**
- * This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
- * The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
- */
-export class EtherTokenWrapper extends ContractWrapper {
- private _etherTokenContractsByAddress: {
- [address: string]: EtherTokenContract;
- } = {};
- private _tokenWrapper: TokenWrapper;
- constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder, tokenWrapper: TokenWrapper) {
- super(web3Wrapper, networkId, abiDecoder);
- this._tokenWrapper = tokenWrapper;
- }
- /**
- * Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
- * to the depositor address. These wrapped ETH tokens can be used in 0x trades and are redeemable for 1-to-1
- * for ETH.
- * @param etherTokenAddress EtherToken address you wish to deposit into.
- * @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
- * @param depositor The hex encoded user Ethereum address that would like to make the deposit.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async depositAsync(
- etherTokenAddress: string,
- amountInWei: BigNumber,
- depositor: string,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
- assert.isValidBaseUnitAmount('amountInWei', amountInWei);
- await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
- const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
- const normalizedDepositorAddress = depositor.toLowerCase();
-
- const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress);
- assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
-
- const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
- const txHash = await wethContract.deposit.sendTransactionAsync({
- from: normalizedDepositorAddress,
- value: amountInWei,
- gas: txOpts.gasLimit,
- gasPrice: txOpts.gasPrice,
- });
- return txHash;
- }
- /**
- * Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the
- * equivalent number of wrapped ETH tokens.
- * @param etherTokenAddress EtherToken address you wish to withdraw from.
- * @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
- * @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawal.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async withdrawAsync(
- etherTokenAddress: string,
- amountInWei: BigNumber,
- withdrawer: string,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isValidBaseUnitAmount('amountInWei', amountInWei);
- assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
- await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
- const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
- const normalizedWithdrawerAddress = withdrawer.toLowerCase();
-
- const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(
- normalizedEtherTokenAddress,
- normalizedWithdrawerAddress,
- );
- assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
-
- const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
- const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
- from: normalizedWithdrawerAddress,
- gas: txOpts.gasLimit,
- gasPrice: txOpts.gasPrice,
- });
- return txHash;
- }
- /**
- * Gets historical logs without creating a subscription
- * @param etherTokenAddress An address of the ether token that emitted the logs.
- * @param eventName The ether token contract event you would like to subscribe to.
- * @param blockRange Block range to get logs from.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
- * @return Array of logs that match the parameters
- */
- public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
- etherTokenAddress: string,
- eventName: EtherTokenEvents,
- blockRange: BlockRange,
- indexFilterValues: IndexedFilterValues,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
- const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
- assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
- assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- const logs = await this._getLogsAsync<ArgsType>(
- normalizedEtherTokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- artifacts.EtherTokenArtifact.abi,
- );
- return logs;
- }
- /**
- * Subscribe to an event type emitted by the Token contract.
- * @param etherTokenAddress The hex encoded address where the ether token is deployed.
- * @param eventName The ether token contract event you would like to subscribe to.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
- * @param callback Callback that gets called when a log is added/removed
- * @return Subscription token used later to unsubscribe
- */
- public subscribe<ArgsType extends EtherTokenContractEventArgs>(
- etherTokenAddress: string,
- eventName: EtherTokenEvents,
- indexFilterValues: IndexedFilterValues,
- callback: EventCallback<ArgsType>,
- ): string {
- assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
- const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
- assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- assert.isFunction('callback', callback);
- const subscriptionToken = this._subscribe<ArgsType>(
- normalizedEtherTokenAddress,
- eventName,
- indexFilterValues,
- artifacts.EtherTokenArtifact.abi,
- callback,
- );
- return subscriptionToken;
- }
- /**
- * Cancel a subscription
- * @param subscriptionToken Subscription token returned by `subscribe()`
- */
- public unsubscribe(subscriptionToken: string): void {
- this._unsubscribe(subscriptionToken);
- }
- /**
- * Cancels all existing subscriptions
- */
- public unsubscribeAll(): void {
- super._unsubscribeAll();
- }
- /**
- * Retrieves the Ethereum address of the EtherToken contract deployed on the network
- * that the user-passed web3 provider is connected to. If it's not Kovan, Ropsten, Rinkeby, Mainnet or TestRPC
- * (networkId: 50), it will return undefined (e.g a private network).
- * @returns The Ethereum address of the EtherToken contract or undefined.
- */
- public getContractAddressIfExists(): string | undefined {
- const networkSpecificArtifact = artifacts.EtherTokenArtifact.networks[this._networkId];
- const contractAddressIfExists = _.isUndefined(networkSpecificArtifact)
- ? undefined
- : networkSpecificArtifact.address;
- return contractAddressIfExists;
- }
- private _invalidateContractInstance(): void {
- this.unsubscribeAll();
- this._etherTokenContractsByAddress = {};
- }
- private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> {
- let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];
- if (!_.isUndefined(etherTokenContract)) {
- return etherTokenContract;
- }
- const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
- artifacts.EtherTokenArtifact,
- etherTokenAddress,
- );
- const contractInstance = new EtherTokenContract(this._web3Wrapper, abi, address);
- etherTokenContract = contractInstance;
- this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
- return etherTokenContract;
- }
-}
diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts
deleted file mode 100644
index 6b5a75a9a..000000000
--- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts
+++ /dev/null
@@ -1,934 +0,0 @@
-import { schemas } from '@0xproject/json-schemas';
-import {
- BlockParamLiteral,
- DecodedLogArgs,
- ECSignature,
- LogEntry,
- LogWithDecodedArgs,
- Order,
- SignedOrder,
-} from '@0xproject/types';
-import { AbiDecoder, BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { artifacts } from '../artifacts';
-import {
- BlockRange,
- EventCallback,
- ExchangeContractErrCodes,
- ExchangeContractErrs,
- IndexedFilterValues,
- MethodOpts,
- OrderAddresses,
- OrderCancellationRequest,
- OrderFillRequest,
- OrderTransactionOpts,
- OrderValues,
- ValidateOrderFillableOpts,
-} from '../types';
-import { assert } from '../utils/assert';
-import { decorators } from '../utils/decorators';
-import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator';
-import { OrderValidationUtils } from '../utils/order_validation_utils';
-import { utils } from '../utils/utils';
-
-import { ContractWrapper } from './contract_wrapper';
-import {
- ExchangeContract,
- ExchangeContractEventArgs,
- ExchangeEvents,
- LogErrorContractEventArgs,
-} from './generated/exchange';
-import { TokenWrapper } from './token_wrapper';
-
-const SHOULD_VALIDATE_BY_DEFAULT = true;
-
-interface ExchangeContractErrCodesToMsgs {
- [exchangeContractErrCodes: number]: string;
-}
-
-/**
- * This class includes all the functionality related to calling methods and subscribing to
- * events of the 0x Exchange smart contract.
- */
-export class ExchangeWrapper extends ContractWrapper {
- private _exchangeContractIfExists?: ExchangeContract;
- private _orderValidationUtils: OrderValidationUtils;
- private _tokenWrapper: TokenWrapper;
- private _exchangeContractErrCodesToMsg: ExchangeContractErrCodesToMsgs = {
- [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
- [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
- [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero,
- [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero,
- [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError,
- [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError,
- };
- private _contractAddressIfExists?: string;
- private _zrxContractAddressIfExists?: string;
- private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
- const orderAddresses: OrderAddresses = [
- order.maker,
- order.taker,
- order.makerTokenAddress,
- order.takerTokenAddress,
- order.feeRecipient,
- ];
- const orderValues: OrderValues = [
- order.makerTokenAmount,
- order.takerTokenAmount,
- order.makerFee,
- order.takerFee,
- order.expirationUnixTimestampSec,
- order.salt,
- ];
- return [orderAddresses, orderValues];
- }
- constructor(
- web3Wrapper: Web3Wrapper,
- networkId: number,
- abiDecoder: AbiDecoder,
- tokenWrapper: TokenWrapper,
- contractAddressIfExists?: string,
- zrxContractAddressIfExists?: string,
- ) {
- super(web3Wrapper, networkId, abiDecoder);
- this._tokenWrapper = tokenWrapper;
- this._orderValidationUtils = new OrderValidationUtils(this);
- this._contractAddressIfExists = contractAddressIfExists;
- this._zrxContractAddressIfExists = zrxContractAddressIfExists;
- }
- /**
- * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total
- * amount that has been filled or cancelled. The remaining takerAmount can be calculated by
- * subtracting the unavailable amount from the total order takerAmount.
- * @param orderHash The hex encoded orderHash for which you would like to retrieve the
- * unavailable takerAmount.
- * @param methodOpts Optional arguments this method accepts.
- * @return The amount of the order (in taker tokens) that has either been filled or cancelled.
- */
- public async getUnavailableTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
-
- const exchangeContract = await this._getExchangeContractAsync();
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- const txData = {};
- let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
- orderHash,
- txData,
- defaultBlock,
- );
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount);
- return unavailableTakerTokenAmount;
- }
- /**
- * Retrieve the takerAmount of an order that has already been filled.
- * @param orderHash The hex encoded orderHash for which you would like to retrieve the filled takerAmount.
- * @param methodOpts Optional arguments this method accepts.
- * @return The amount of the order (in taker tokens) that has already been filled.
- */
- public async getFilledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
-
- const exchangeContract = await this._getExchangeContractAsync();
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- const txData = {};
- let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, txData, defaultBlock);
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
- return fillAmountInBaseUnits;
- }
- /**
- * Retrieve the takerAmount of an order that has been cancelled.
- * @param orderHash The hex encoded orderHash for which you would like to retrieve the
- * cancelled takerAmount.
- * @param methodOpts Optional arguments this method accepts.
- * @return The amount of the order (in taker tokens) that has been cancelled.
- */
- public async getCancelledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
-
- const exchangeContract = await this._getExchangeContractAsync();
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- const txData = {};
- let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, txData, defaultBlock);
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
- return cancelledAmountInBaseUnits;
- }
- /**
- * Fills a signed order with an amount denominated in baseUnits of the taker token.
- * Since the order in which transactions are included in the next block is indeterminate, race-conditions
- * could arise where a users balance or allowance changes before the fillOrder executes. Because of this,
- * we allow you to specify `shouldThrowOnInsufficientBalanceOrAllowance`.
- * If false, the smart contract will not throw if the parties
- * do not have sufficient balances/allowances, preserving gas costs. Setting it to true forgoes this check
- * and causes the smart contract to throw (using all the gas supplied) instead.
- * @param signedOrder An object that conforms to the SignedOrder interface.
- * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that
- * you wish to fill.
- * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw
- * if upon execution the tokens cannot be transferred.
- * @param takerAddress The user Ethereum address who would like to fill this order.
- * Must be available via the supplied Web3.Provider
- * passed to 0x.js.
- * @param orderTransactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async fillOrderAsync(
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
-
- const exchangeInstance = await this._getExchangeContractAsync();
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
-
- const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
-
- const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync(
- orderAddresses,
- orderValues,
- fillTakerTokenAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- signedOrder.ecSignature.v,
- signedOrder.ecSignature.r,
- signedOrder.ecSignature.s,
- {
- from: normalizedTakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Sequentially and atomically fills signedOrders up to the specified takerTokenFillAmount.
- * If the fill amount is reached - it succeeds and does not fill the rest of the orders.
- * If fill amount is not reached - it fills as much of the fill amount as possible and succeeds.
- * @param signedOrders The array of signedOrders that you would like to fill until
- * takerTokenFillAmount is reached.
- * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
- * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw if
- * upon execution any of the tokens cannot be transferred.
- * If set to false, the call will continue to fill subsequent
- * signedOrders even when some cannot be filled.
- * @param takerAddress The user Ethereum address who would like to fill these
- * orders. Must be available via the supplied Web3.Provider
- * passed to 0x.js.
- * @param orderTransactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async fillOrdersUpToAsync(
- signedOrders: SignedOrder[],
- fillTakerTokenAmount: BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
- const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
- assert.hasAtMostOneUniqueValue(
- takerTokenAddresses,
- ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed,
- );
- const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress);
- assert.hasAtMostOneUniqueValue(
- exchangeContractAddresses,
- ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
- );
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
-
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- let filledTakerTokenAmount = new BigNumber(0);
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- for (const signedOrder of signedOrders) {
- const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount.minus(filledTakerTokenAmount),
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount);
- if (filledTakerTokenAmount.eq(fillTakerTokenAmount)) {
- break;
- }
- }
- }
-
- if (_.isEmpty(signedOrders)) {
- throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- }
-
- const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => {
- return [
- ...ExchangeWrapper._getOrderAddressesAndValues(signedOrder),
- signedOrder.ecSignature.v,
- signedOrder.ecSignature.r,
- signedOrder.ecSignature.s,
- ];
- });
- // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
- const [orderAddressesArray, orderValuesArray, vArray, rArray, sArray] = _.unzip<any>(
- orderAddressesValuesAndSignatureArray,
- );
-
- const exchangeInstance = await this._getExchangeContractAsync();
- const txHash = await exchangeInstance.fillOrdersUpTo.sendTransactionAsync(
- orderAddressesArray,
- orderValuesArray,
- fillTakerTokenAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- vArray,
- rArray,
- sArray,
- {
- from: normalizedTakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Batch version of fillOrderAsync.
- * Executes multiple fills atomically in a single transaction.
- * If shouldThrowOnInsufficientBalanceOrAllowance is set to false, it will continue filling subsequent orders even
- * when earlier ones fail.
- * When shouldThrowOnInsufficientBalanceOrAllowance is set to true, if any fill fails, the entire batch fails.
- * @param orderFillRequests An array of objects that conform to the
- * OrderFillRequest interface.
- * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw
- * if upon execution any of the tokens cannot be
- * transferred. If set to false, the call will continue to
- * fill subsequent signedOrders even when some
- * cannot be filled.
- * @param takerAddress The user Ethereum address who would like to fill
- * these orders. Must be available via the supplied
- * Web3.Provider passed to 0x.js.
- * @param orderTransactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async batchFillOrdersAsync(
- orderFillRequests: OrderFillRequest[],
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
- const exchangeContractAddresses = _.map(
- orderFillRequests,
- orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
- );
- assert.hasAtMostOneUniqueValue(
- exchangeContractAddresses,
- ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
- );
- assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- for (const orderFillRequest of orderFillRequests) {
- await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- orderFillRequest.signedOrder,
- orderFillRequest.takerTokenFillAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
- }
- if (_.isEmpty(orderFillRequests)) {
- throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- }
-
- const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => {
- return [
- ...ExchangeWrapper._getOrderAddressesAndValues(orderFillRequest.signedOrder),
- orderFillRequest.takerTokenFillAmount,
- orderFillRequest.signedOrder.ecSignature.v,
- orderFillRequest.signedOrder.ecSignature.r,
- orderFillRequest.signedOrder.ecSignature.s,
- ];
- });
- // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
- const [orderAddressesArray, orderValuesArray, fillTakerTokenAmounts, vArray, rArray, sArray] = _.unzip<any>(
- orderAddressesValuesAmountsAndSignatureArray,
- );
-
- const exchangeInstance = await this._getExchangeContractAsync();
- const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync(
- orderAddressesArray,
- orderValuesArray,
- fillTakerTokenAmounts,
- shouldThrowOnInsufficientBalanceOrAllowance,
- vArray,
- rArray,
- sArray,
- {
- from: normalizedTakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled,
- * the fill order is abandoned.
- * @param signedOrder An object that conforms to the SignedOrder interface. The
- * signedOrder you wish to fill.
- * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
- * @param takerAddress The user Ethereum address who would like to fill this order.
- * Must be available via the supplied Web3.Provider passed to 0x.js.
- * @param orderTransactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async fillOrKillOrderAsync(
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
-
- const exchangeInstance = await this._getExchangeContractAsync();
-
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
-
- const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
- const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync(
- orderAddresses,
- orderValues,
- fillTakerTokenAmount,
- signedOrder.ecSignature.v,
- signedOrder.ecSignature.r,
- signedOrder.ecSignature.s,
- {
- from: normalizedTakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Batch version of fillOrKill. Allows a taker to specify a batch of orders that will either be atomically
- * filled (each to the specified fillAmount) or aborted.
- * @param orderFillRequests An array of objects that conform to the OrderFillRequest interface.
- * @param takerAddress The user Ethereum address who would like to fill there orders.
- * Must be available via the supplied Web3.Provider passed to 0x.js.
- * @param orderTransactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async batchFillOrKillAsync(
- orderFillRequests: OrderFillRequest[],
- takerAddress: string,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
- const exchangeContractAddresses = _.map(
- orderFillRequests,
- orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
- );
- assert.hasAtMostOneUniqueValue(
- exchangeContractAddresses,
- ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
- );
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
- if (_.isEmpty(orderFillRequests)) {
- throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- }
- const exchangeInstance = await this._getExchangeContractAsync();
-
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- for (const orderFillRequest of orderFillRequests) {
- await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- orderFillRequest.signedOrder,
- orderFillRequest.takerTokenFillAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
- }
-
- const orderAddressesValuesAndTakerTokenFillAmounts = _.map(orderFillRequests, request => {
- return [
- ...ExchangeWrapper._getOrderAddressesAndValues(request.signedOrder),
- request.takerTokenFillAmount,
- request.signedOrder.ecSignature.v,
- request.signedOrder.ecSignature.r,
- request.signedOrder.ecSignature.s,
- ];
- });
-
- // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
- const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>(
- orderAddressesValuesAndTakerTokenFillAmounts,
- );
- const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync(
- orderAddresses,
- orderValues,
- fillTakerTokenAmounts,
- vParams,
- rParams,
- sParams,
- {
- from: normalizedTakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Cancel a given fill amount of an order. Cancellations are cumulative.
- * @param order An object that conforms to the Order or SignedOrder interface.
- * The order you would like to cancel.
- * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
- * @param transactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async cancelOrderAsync(
- order: Order | SignedOrder,
- cancelTakerTokenAmount: BigNumber,
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema('order', order, schemas.orderSchema);
- assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount);
- await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
- const normalizedMakerAddress = order.maker.toLowerCase();
-
- const exchangeInstance = await this._getExchangeContractAsync();
-
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- const orderHash = utils.getOrderHashHex(order);
- const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- OrderValidationUtils.validateCancelOrderThrowIfInvalid(
- order,
- cancelTakerTokenAmount,
- unavailableTakerTokenAmount,
- );
- }
-
- const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
- const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync(
- orderAddresses,
- orderValues,
- cancelTakerTokenAmount,
- {
- from: normalizedMakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Batch version of cancelOrderAsync. Atomically cancels multiple orders in a single transaction.
- * All orders must be from the same maker.
- * @param orderCancellationRequests An array of objects that conform to the OrderCancellationRequest
- * interface.
- * @param transactionOpts Optional arguments this method accepts.
- * @return Transaction hash.
- */
- @decorators.asyncZeroExErrorHandler
- public async batchCancelOrdersAsync(
- orderCancellationRequests: OrderCancellationRequest[],
- orderTransactionOpts: OrderTransactionOpts = {},
- ): Promise<string> {
- assert.doesConformToSchema(
- 'orderCancellationRequests',
- orderCancellationRequests,
- schemas.orderCancellationRequestsSchema,
- );
- const exchangeContractAddresses = _.map(
- orderCancellationRequests,
- orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
- );
- assert.hasAtMostOneUniqueValue(
- exchangeContractAddresses,
- ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
- );
- const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
- assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
- const maker = makers[0];
- await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
- const normalizedMakerAddress = maker.toLowerCase();
-
- const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
- ? SHOULD_VALIDATE_BY_DEFAULT
- : orderTransactionOpts.shouldValidate;
- if (shouldValidate) {
- for (const orderCancellationRequest of orderCancellationRequests) {
- const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
- const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- OrderValidationUtils.validateCancelOrderThrowIfInvalid(
- orderCancellationRequest.order,
- orderCancellationRequest.takerTokenCancelAmount,
- unavailableTakerTokenAmount,
- );
- }
- }
- if (_.isEmpty(orderCancellationRequests)) {
- throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- }
- const exchangeInstance = await this._getExchangeContractAsync();
- const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => {
- return [
- ...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order),
- cancellationRequest.takerTokenCancelAmount,
- ];
- });
- // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
- const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>(
- orderAddressesValuesAndTakerTokenCancelAmounts,
- );
- const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(
- orderAddresses,
- orderValues,
- cancelTakerTokenAmounts,
- {
- from: normalizedMakerAddress,
- gas: orderTransactionOpts.gasLimit,
- gasPrice: orderTransactionOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Subscribe to an event type emitted by the Exchange contract.
- * @param eventName The exchange contract event you would like to subscribe to.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
- * @param callback Callback that gets called when a log is added/removed
- * @return Subscription token used later to unsubscribe
- */
- public subscribe<ArgsType extends ExchangeContractEventArgs>(
- eventName: ExchangeEvents,
- indexFilterValues: IndexedFilterValues,
- callback: EventCallback<ArgsType>,
- ): string {
- assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- assert.isFunction('callback', callback);
- const exchangeContractAddress = this.getContractAddress();
- const subscriptionToken = this._subscribe<ArgsType>(
- exchangeContractAddress,
- eventName,
- indexFilterValues,
- artifacts.ExchangeArtifact.abi,
- callback,
- );
- return subscriptionToken;
- }
- /**
- * Cancel a subscription
- * @param subscriptionToken Subscription token returned by `subscribe()`
- */
- public unsubscribe(subscriptionToken: string): void {
- this._unsubscribe(subscriptionToken);
- }
- /**
- * Cancels all existing subscriptions
- */
- public unsubscribeAll(): void {
- super._unsubscribeAll();
- }
- /**
- * Gets historical logs without creating a subscription
- * @param eventName The exchange contract event you would like to subscribe to.
- * @param blockRange Block range to get logs from.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
- * @return Array of logs that match the parameters
- */
- public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
- eventName: ExchangeEvents,
- blockRange: BlockRange,
- indexFilterValues: IndexedFilterValues,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
- assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- const exchangeContractAddress = this.getContractAddress();
- const logs = await this._getLogsAsync<ArgsType>(
- exchangeContractAddress,
- eventName,
- blockRange,
- indexFilterValues,
- artifacts.ExchangeArtifact.abi,
- );
- return logs;
- }
- /**
- * Retrieves the Ethereum address of the Exchange contract deployed on the network
- * that the user-passed web3 provider is connected to.
- * @returns The Ethereum address of the Exchange contract being used.
- */
- public getContractAddress(): string {
- const contractAddress = this._getContractAddress(artifacts.ExchangeArtifact, this._contractAddressIfExists);
- return contractAddress;
- }
- /**
- * Checks if order is still fillable and throws an error otherwise. Useful for orderbook
- * pruning where you want to remove stale orders without knowing who the taker will be.
- * @param signedOrder An object that conforms to the SignedOrder interface. The
- * signedOrder you wish to validate.
- * @param opts An object that conforms to the ValidateOrderFillableOpts
- * interface. Allows specifying a specific fillTakerTokenAmount
- * to validate for.
- */
- public async validateOrderFillableOrThrowAsync(
- signedOrder: SignedOrder,
- opts?: ValidateOrderFillableOpts,
- ): Promise<void> {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- const zrxTokenAddress = this.getZRXTokenAddress();
- const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined;
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- await this._orderValidationUtils.validateOrderFillableOrThrowAsync(
- exchangeTradeEmulator,
- signedOrder,
- zrxTokenAddress,
- expectedFillTakerTokenAmount,
- );
- }
- /**
- * Checks if order fill will succeed and throws an error otherwise.
- * @param signedOrder An object that conforms to the SignedOrder interface. The
- * signedOrder you wish to fill.
- * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
- * @param takerAddress The user Ethereum address who would like to fill this order.
- * Must be available via the supplied Web3.Provider passed to 0x.js.
- */
- public async validateFillOrderThrowIfInvalidAsync(
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string,
- ): Promise<void> {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
- /**
- * Checks if cancelling a given order will succeed and throws an informative error if it won't.
- * @param order An object that conforms to the Order or SignedOrder interface.
- * The order you would like to cancel.
- * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
- */
- public async validateCancelOrderThrowIfInvalidAsync(
- order: Order,
- cancelTakerTokenAmount: BigNumber,
- ): Promise<void> {
- assert.doesConformToSchema('order', order, schemas.orderSchema);
- assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
- const orderHash = utils.getOrderHashHex(order);
- const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- OrderValidationUtils.validateCancelOrderThrowIfInvalid(
- order,
- cancelTakerTokenAmount,
- unavailableTakerTokenAmount,
- );
- }
- /**
- * Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't.
- * @param signedOrder An object that conforms to the SignedOrder interface. The
- * signedOrder you wish to fill.
- * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
- * @param takerAddress The user Ethereum address who would like to fill this order.
- * Must be available via the supplied Web3.Provider passed to 0x.js.
- */
- public async validateFillOrKillOrderThrowIfInvalidAsync(
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string,
- ): Promise<void> {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
- const normalizedTakerAddress = takerAddress.toLowerCase();
- const zrxTokenAddress = this.getZRXTokenAddress();
- const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
- await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount,
- normalizedTakerAddress,
- zrxTokenAddress,
- );
- }
- /**
- * Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing:
- * `(fillTakerTokenAmount * makerTokenAmount) / takerTokenAmount`.
- * 0x Protocol does not accept any trades that result in large rounding errors. This means that tokens with few or
- * no decimals can only be filled in quantities and ratios that avoid large rounding errors.
- * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that you wish to fill.
- * @param takerTokenAmount The order size on the taker side
- * @param makerTokenAmount The order size on the maker side
- */
- public async isRoundingErrorAsync(
- fillTakerTokenAmount: BigNumber,
- takerTokenAmount: BigNumber,
- makerTokenAmount: BigNumber,
- ): Promise<boolean> {
- assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
- assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount);
- assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount);
- const exchangeInstance = await this._getExchangeContractAsync();
- const isRoundingError = await exchangeInstance.isRoundingError.callAsync(
- fillTakerTokenAmount,
- takerTokenAmount,
- makerTokenAmount,
- );
- return isRoundingError;
- }
- /**
- * Checks if logs contain LogError, which is emitted by Exchange contract on transaction failure.
- * @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
- */
- public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | LogEntry>): void {
- const errLog = _.find(logs, {
- event: ExchangeEvents.LogError,
- });
- if (!_.isUndefined(errLog)) {
- const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
- const errCode = logArgs.errorId;
- const errMessage = this._exchangeContractErrCodesToMsg[errCode];
- throw new Error(errMessage);
- }
- }
- /**
- * Returns the ZRX token address used by the exchange contract.
- * @return Address of ZRX token
- */
- public getZRXTokenAddress(): string {
- const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists);
- return contractAddress;
- }
- private _invalidateContractInstances(): void {
- this.unsubscribeAll();
- delete this._exchangeContractIfExists;
- }
- private async _isValidSignatureUsingContractCallAsync(
- dataHex: string,
- ecSignature: ECSignature,
- signerAddressHex: string,
- ): Promise<boolean> {
- assert.isHexString('dataHex', dataHex);
- assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema);
- assert.isETHAddressHex('signerAddressHex', signerAddressHex);
- const normalizedSignerAddress = signerAddressHex.toLowerCase();
-
- const exchangeInstance = await this._getExchangeContractAsync();
-
- const isValidSignature = await exchangeInstance.isValidSignature.callAsync(
- normalizedSignerAddress,
- dataHex,
- ecSignature.v,
- ecSignature.r,
- ecSignature.s,
- );
- return isValidSignature;
- }
- private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> {
- const exchangeInstance = await this._getExchangeContractAsync();
- const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
- const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
- return orderHashHex;
- }
- private async _getExchangeContractAsync(): Promise<ExchangeContract> {
- if (!_.isUndefined(this._exchangeContractIfExists)) {
- return this._exchangeContractIfExists;
- }
- const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
- artifacts.ExchangeArtifact,
- this._contractAddressIfExists,
- );
- const contractInstance = new ExchangeContract(this._web3Wrapper, abi, address);
- this._exchangeContractIfExists = contractInstance;
- return this._exchangeContractIfExists;
- }
- private async _getTokenTransferProxyAddressAsync(): Promise<string> {
- const exchangeInstance = await this._getExchangeContractAsync();
- const tokenTransferProxyAddress = await exchangeInstance.TOKEN_TRANSFER_PROXY_CONTRACT.callAsync();
- const tokenTransferProxyAddressLowerCase = tokenTransferProxyAddress.toLowerCase();
- return tokenTransferProxyAddressLowerCase;
- }
-} // tslint:disable:max-file-line-count
diff --git a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts
deleted file mode 100644
index e1806c6f2..000000000
--- a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { artifacts } from '../artifacts';
-import { Token, TokenMetadata } from '../types';
-import { assert } from '../utils/assert';
-import { constants } from '../utils/constants';
-
-import { ContractWrapper } from './contract_wrapper';
-import { TokenRegistryContract } from './generated/token_registry';
-
-/**
- * This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
- */
-export class TokenRegistryWrapper extends ContractWrapper {
- private _tokenRegistryContractIfExists?: TokenRegistryContract;
- private _contractAddressIfExists?: string;
- private static _createTokenFromMetadata(metadata: TokenMetadata): Token | undefined {
- if (metadata[0] === constants.NULL_ADDRESS) {
- return undefined;
- }
- const token = {
- address: metadata[0],
- name: metadata[1],
- symbol: metadata[2],
- decimals: metadata[3],
- };
- return token;
- }
- constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
- super(web3Wrapper, networkId);
- this._contractAddressIfExists = contractAddressIfExists;
- }
- /**
- * Retrieves all the tokens currently listed in the Token Registry smart contract
- * @return An array of objects that conform to the Token interface.
- */
- public async getTokensAsync(): Promise<Token[]> {
- const addresses = await this.getTokenAddressesAsync();
- const tokenPromises: Array<Promise<Token | undefined>> = _.map(addresses, async (address: string) =>
- this.getTokenIfExistsAsync(address),
- );
- const tokens = await Promise.all(tokenPromises);
- return tokens as Token[];
- }
- /**
- * Retrieves all the addresses of the tokens currently listed in the Token Registry smart contract
- * @return An array of token addresses.
- */
- public async getTokenAddressesAsync(): Promise<string[]> {
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
- const lowerCaseAddresses = _.map(addresses, address => address.toLowerCase());
- return lowerCaseAddresses;
- }
- /**
- * Retrieves a token by address currently listed in the Token Registry smart contract
- * @return An object that conforms to the Token interface or undefined if token not found.
- */
- public async getTokenIfExistsAsync(address: string): Promise<Token | undefined> {
- assert.isETHAddressHex('address', address);
- const normalizedAddress = address.toLowerCase();
-
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(normalizedAddress);
- const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
- return token;
- }
- public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string | undefined> {
- assert.isString('symbol', symbol);
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
- if (addressIfExists === constants.NULL_ADDRESS) {
- return undefined;
- }
- return addressIfExists;
- }
- public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string | undefined> {
- assert.isString('name', name);
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
- if (addressIfExists === constants.NULL_ADDRESS) {
- return undefined;
- }
- return addressIfExists;
- }
- public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token | undefined> {
- assert.isString('symbol', symbol);
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
- const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
- return token;
- }
- public async getTokenByNameIfExistsAsync(name: string): Promise<Token | undefined> {
- assert.isString('name', name);
- const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
- const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
- return token;
- }
- /**
- * Retrieves the Ethereum address of the TokenRegistry contract deployed on the network
- * that the user-passed web3 provider is connected to.
- * @returns The Ethereum address of the TokenRegistry contract being used.
- */
- public getContractAddress(): string {
- const contractAddress = this._getContractAddress(
- artifacts.TokenRegistryArtifact,
- this._contractAddressIfExists,
- );
- return contractAddress;
- }
- private _invalidateContractInstance(): void {
- delete this._tokenRegistryContractIfExists;
- }
- private async _getTokenRegistryContractAsync(): Promise<TokenRegistryContract> {
- if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
- return this._tokenRegistryContractIfExists;
- }
- const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
- artifacts.TokenRegistryArtifact,
- this._contractAddressIfExists,
- );
- const contractInstance = new TokenRegistryContract(this._web3Wrapper, abi, address);
- this._tokenRegistryContractIfExists = contractInstance;
- return this._tokenRegistryContractIfExists;
- }
-}
diff --git a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts
deleted file mode 100644
index 211c7dfb4..000000000
--- a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { artifacts } from '../artifacts';
-import { assert } from '../utils/assert';
-
-import { ContractWrapper } from './contract_wrapper';
-import { TokenTransferProxyContract } from './generated/token_transfer_proxy';
-
-/**
- * This class includes the functionality related to interacting with the TokenTransferProxy contract.
- */
-export class TokenTransferProxyWrapper extends ContractWrapper {
- private _tokenTransferProxyContractIfExists?: TokenTransferProxyContract;
- private _contractAddressIfExists?: string;
- constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
- super(web3Wrapper, networkId);
- this._contractAddressIfExists = contractAddressIfExists;
- }
- /**
- * Check if the Exchange contract address is authorized by the TokenTransferProxy contract.
- * @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
- * @return Whether the exchangeContractAddress is authorized.
- */
- public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
- assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
- const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
- const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
- const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(
- normalizedExchangeContractAddress,
- );
- return isAuthorized;
- }
- /**
- * Get the list of all Exchange contract addresses authorized by the TokenTransferProxy contract.
- * @return The list of authorized addresses.
- */
- public async getAuthorizedAddressesAsync(): Promise<string[]> {
- const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
- const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.callAsync();
- return authorizedAddresses;
- }
- /**
- * Retrieves the Ethereum address of the TokenTransferProxy contract deployed on the network
- * that the user-passed web3 provider is connected to.
- * @returns The Ethereum address of the TokenTransferProxy contract being used.
- */
- public getContractAddress(): string {
- const contractAddress = this._getContractAddress(
- artifacts.TokenTransferProxyArtifact,
- this._contractAddressIfExists,
- );
- return contractAddress;
- }
- private _invalidateContractInstance(): void {
- delete this._tokenTransferProxyContractIfExists;
- }
- private async _getTokenTransferProxyContractAsync(): Promise<TokenTransferProxyContract> {
- if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
- return this._tokenTransferProxyContractIfExists;
- }
- const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
- artifacts.TokenTransferProxyArtifact,
- this._contractAddressIfExists,
- );
- const contractInstance = new TokenTransferProxyContract(this._web3Wrapper, abi, address);
- this._tokenTransferProxyContractIfExists = contractInstance;
- return this._tokenTransferProxyContractIfExists;
- }
-}
diff --git a/packages/0x.js/src/contract_wrappers/token_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_wrapper.ts
deleted file mode 100644
index e350dfb92..000000000
--- a/packages/0x.js/src/contract_wrappers/token_wrapper.ts
+++ /dev/null
@@ -1,434 +0,0 @@
-import { schemas } from '@0xproject/json-schemas';
-import { LogWithDecodedArgs } from '@0xproject/types';
-import { AbiDecoder, BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { artifacts } from '../artifacts';
-import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types';
-import { assert } from '../utils/assert';
-import { constants } from '../utils/constants';
-
-import { ContractWrapper } from './contract_wrapper';
-import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
-import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
-
-/**
- * This class includes all the functionality related to interacting with ERC20 token contracts.
- * All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
- * to the 0x Proxy smart contract.
- */
-export class TokenWrapper extends ContractWrapper {
- public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
- private _tokenContractsByAddress: { [address: string]: TokenContract };
- private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
- constructor(
- web3Wrapper: Web3Wrapper,
- networkId: number,
- abiDecoder: AbiDecoder,
- tokenTransferProxyWrapper: TokenTransferProxyWrapper,
- ) {
- super(web3Wrapper, networkId, abiDecoder);
- this._tokenContractsByAddress = {};
- this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
- }
- /**
- * Retrieves an owner's ERC20 token balance.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check.
- * @param methodOpts Optional arguments this method accepts.
- * @return The owner's ERC20 token balance in base units.
- */
- public async getBalanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- methodOpts?: MethodOpts,
- ): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
-
- const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- const txData = {};
- let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- balance = new BigNumber(balance);
- return balance;
- }
- /**
- * Sets the spender's allowance to a specified number of baseUnits on behalf of the owner address.
- * Equivalent to the ERC20 spec method `approve`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
- * for spenderAddress.
- * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
- * @param amountInBaseUnits The allowance amount you would like to set.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async setAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- spenderAddress: string,
- amountInBaseUnits: BigNumber,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('spenderAddress', spenderAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedSpenderAddress = spenderAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
- const txHash = await tokenContract.approve.sendTransactionAsync(normalizedSpenderAddress, amountInBaseUnits, {
- from: normalizedOwnerAddress,
- gas: txOpts.gasLimit,
- gasPrice: txOpts.gasPrice,
- });
- return txHash;
- }
- /**
- * Sets the spender's allowance to an unlimited number of baseUnits on behalf of the owner address.
- * Equivalent to the ERC20 spec method `approve`.
- * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
- * allowances set to the max amount (e.g ZRX, WETH)
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
- * for spenderAddress.
- * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async setUnlimitedAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- spenderAddress: string,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isETHAddressHex('spenderAddress', spenderAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
- const normalizedSpenderAddress = spenderAddress.toLowerCase();
- const txHash = await this.setAllowanceAsync(
- normalizedTokenAddress,
- normalizedOwnerAddress,
- normalizedSpenderAddress,
- this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
- txOpts,
- );
- return txHash;
- }
- /**
- * Retrieves the owners allowance in baseUnits set to the spender's address.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose allowance to spenderAddress
- * you would like to retrieve.
- * @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
- * @param methodOpts Optional arguments this method accepts.
- */
- public async getAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- spenderAddress: string,
- methodOpts?: MethodOpts,
- ): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isETHAddressHex('spenderAddress', spenderAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
- const normalizedSpenderAddress = spenderAddress.toLowerCase();
-
- const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- const txData = {};
- let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
- normalizedOwnerAddress,
- normalizedSpenderAddress,
- txData,
- defaultBlock,
- );
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
- return allowanceInBaseUnits;
- }
- /**
- * Retrieves the owner's allowance in baseUnits set to the 0x proxy contract.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
- * @param methodOpts Optional arguments this method accepts.
- */
- public async getProxyAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- methodOpts?: MethodOpts,
- ): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
-
- const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
- const allowanceInBaseUnits = await this.getAllowanceAsync(
- normalizedTokenAddress,
- normalizedOwnerAddress,
- proxyAddress,
- methodOpts,
- );
- return allowanceInBaseUnits;
- }
- /**
- * Sets the 0x proxy contract's allowance to a specified number of a tokens' baseUnits on behalf
- * of an owner address.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
- * for the Proxy contract.
- * @param amountInBaseUnits The allowance amount specified in baseUnits.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async setProxyAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- amountInBaseUnits: BigNumber,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
- const txHash = await this.setAllowanceAsync(
- normalizedTokenAddress,
- normalizedOwnerAddress,
- proxyAddress,
- amountInBaseUnits,
- txOpts,
- );
- return txHash;
- }
- /**
- * Sets the 0x proxy contract's allowance to a unlimited number of a tokens' baseUnits on behalf
- * of an owner address.
- * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
- * allowances set to the max amount (e.g ZRX, WETH)
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
- * for the Proxy contract.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async setUnlimitedProxyAllowanceAsync(
- tokenAddress: string,
- ownerAddress: string,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedOwnerAddress = ownerAddress.toLowerCase();
- const txHash = await this.setProxyAllowanceAsync(
- normalizedTokenAddress,
- normalizedOwnerAddress,
- this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
- txOpts,
- );
- return txHash;
- }
- /**
- * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param fromAddress The hex encoded user Ethereum address that will send the funds.
- * @param toAddress The hex encoded user Ethereum address that will receive the funds.
- * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async transferAsync(
- tokenAddress: string,
- fromAddress: string,
- toAddress: string,
- amountInBaseUnits: BigNumber,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isETHAddressHex('toAddress', toAddress);
- await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedFromAddress = fromAddress.toLowerCase();
- const normalizedToAddress = toAddress.toLowerCase();
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
-
- const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
- if (fromAddressBalance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientBalanceForTransfer);
- }
-
- const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, {
- from: normalizedFromAddress,
- gas: txOpts.gasLimit,
- gasPrice: txOpts.gasPrice,
- });
- return txHash;
- }
- /**
- * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
- * Requires the fromAddress to have sufficient funds and to have approved an allowance of
- * `amountInBaseUnits` to `senderAddress`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param fromAddress The hex encoded user Ethereum address whose funds are being sent.
- * @param toAddress The hex encoded user Ethereum address that will receive the funds.
- * @param senderAddress The hex encoded user Ethereum address whose initiates the fund transfer. The
- * `fromAddress` must have set an allowance to the `senderAddress`
- * before this call.
- * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
- * @param txOpts Transaction parameters.
- * @return Transaction hash.
- */
- public async transferFromAsync(
- tokenAddress: string,
- fromAddress: string,
- toAddress: string,
- senderAddress: string,
- amountInBaseUnits: BigNumber,
- txOpts: TransactionOpts = {},
- ): Promise<string> {
- assert.isETHAddressHex('toAddress', toAddress);
- assert.isETHAddressHex('fromAddress', fromAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
- const normalizedToAddress = toAddress.toLowerCase();
- const normalizedFromAddress = fromAddress.toLowerCase();
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- const normalizedSenderAddress = senderAddress.toLowerCase();
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
-
- const fromAddressAllowance = await this.getAllowanceAsync(
- normalizedTokenAddress,
- normalizedFromAddress,
- normalizedSenderAddress,
- );
- if (fromAddressAllowance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientAllowanceForTransfer);
- }
-
- const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
- if (fromAddressBalance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientBalanceForTransfer);
- }
-
- const txHash = await tokenContract.transferFrom.sendTransactionAsync(
- normalizedFromAddress,
- normalizedToAddress,
- amountInBaseUnits,
- {
- from: normalizedSenderAddress,
- gas: txOpts.gasLimit,
- gasPrice: txOpts.gasPrice,
- },
- );
- return txHash;
- }
- /**
- * Subscribe to an event type emitted by the Token contract.
- * @param tokenAddress The hex encoded address where the ERC20 token is deployed.
- * @param eventName The token contract event you would like to subscribe to.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
- * @param callback Callback that gets called when a log is added/removed
- * @return Subscription token used later to unsubscribe
- */
- public subscribe<ArgsType extends TokenContractEventArgs>(
- tokenAddress: string,
- eventName: TokenEvents,
- indexFilterValues: IndexedFilterValues,
- callback: EventCallback<ArgsType>,
- ): string {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- assert.isFunction('callback', callback);
- const subscriptionToken = this._subscribe<ArgsType>(
- normalizedTokenAddress,
- eventName,
- indexFilterValues,
- artifacts.TokenArtifact.abi,
- callback,
- );
- return subscriptionToken;
- }
- /**
- * Cancel a subscription
- * @param subscriptionToken Subscription token returned by `subscribe()`
- */
- public unsubscribe(subscriptionToken: string): void {
- this._unsubscribe(subscriptionToken);
- }
- /**
- * Cancels all existing subscriptions
- */
- public unsubscribeAll(): void {
- super._unsubscribeAll();
- }
- /**
- * Gets historical logs without creating a subscription
- * @param tokenAddress An address of the token that emitted the logs.
- * @param eventName The token contract event you would like to subscribe to.
- * @param blockRange Block range to get logs from.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
- * @return Array of logs that match the parameters
- */
- public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
- tokenAddress: string,
- eventName: TokenEvents,
- blockRange: BlockRange,
- indexFilterValues: IndexedFilterValues,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
- assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- const logs = await this._getLogsAsync<ArgsType>(
- normalizedTokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- artifacts.TokenArtifact.abi,
- );
- return logs;
- }
- private _invalidateContractInstances(): void {
- this.unsubscribeAll();
- this._tokenContractsByAddress = {};
- }
- private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
- const normalizedTokenAddress = tokenAddress.toLowerCase();
- let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
- if (!_.isUndefined(tokenContract)) {
- return tokenContract;
- }
- const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
- artifacts.TokenArtifact,
- normalizedTokenAddress,
- );
- const contractInstance = new TokenContract(this._web3Wrapper, abi, address);
- tokenContract = contractInstance;
- this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
- return tokenContract;
- }
-}
diff --git a/packages/0x.js/src/globals.d.ts b/packages/0x.js/src/globals.d.ts
index 3e8ea21bc..94e63a32d 100644
--- a/packages/0x.js/src/globals.d.ts
+++ b/packages/0x.js/src/globals.d.ts
@@ -1,50 +1,6 @@
-declare module 'web3_beta';
-declare module 'chai-bignumber';
-declare module 'dirty-chai';
-declare module 'request-promise-native';
-declare module 'web3-provider-engine';
-declare module 'web3-provider-engine/subproviders/rpc';
-declare module 'publish-release';
-
-// semver-sort declarations
-declare module 'semver-sort' {
- const desc: (versions: string[]) => string[];
-}
-
-// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
-// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
-// disallow `namespace`, we disable tslint for the following.
-/* tslint:disable */
-declare namespace Chai {
- interface Assertion {
- bignumber: Assertion;
- // HACK: In order to comply with chai-as-promised we make eventually a `PromisedAssertion` not an `Assertion`
- eventually: PromisedAssertion;
- }
-}
-/* tslint:enable */
-
declare module '*.json' {
const json: any;
/* tslint:disable */
export default json;
/* tslint:enable */
}
-
-declare module 'ethereumjs-abi' {
- const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
-}
-
-// truffle-hdwallet-provider declarations
-declare module 'truffle-hdwallet-provider' {
- import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types';
- import * as Web3 from 'web3';
- class HDWalletProvider implements Web3.Provider {
- constructor(mnemonic: string, rpcUrl: string);
- public sendAsync(
- payload: JSONRPCRequestPayload,
- callback: (err: Error, result: JSONRPCResponsePayload) => void,
- ): void;
- }
- export = HDWalletProvider;
-}
diff --git a/packages/0x.js/src/globalsAugment.d.ts b/packages/0x.js/src/globalsAugment.d.ts
deleted file mode 100644
index 3e2f2216b..000000000
--- a/packages/0x.js/src/globalsAugment.d.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { BigNumber } from '@0xproject/utils';
-
-// HACK: This module overrides the Chai namespace so that we can use BigNumber types inside.
-// Source: https://github.com/Microsoft/TypeScript/issues/7352#issuecomment-191547232
-declare global {
- // HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
- // interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
- // disallow `namespace`, we disable tslint for the following.
- /* tslint:disable */
- namespace Chai {
- interface NumberComparer {
- (value: number | BigNumber, message?: string): Assertion;
- }
- interface NumericComparison {
- greaterThan: NumberComparer;
- }
- }
- /* tslint:enable */
- interface DecodedLogArg {
- name: string;
- value: string | BigNumber;
- }
-}
diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts
index e353a1d3d..2ba60e730 100644
--- a/packages/0x.js/src/index.ts
+++ b/packages/0x.js/src/index.ts
@@ -1,61 +1,66 @@
export { ZeroEx } from './0x';
+export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
+
export {
- ZeroExError,
- EventCallback,
ExchangeContractErrs,
- ContractEvent,
- Token,
- IndexedFilterValues,
- BlockRange,
- OrderCancellationRequest,
- OrderFillRequest,
- ContractEventArgs,
- Web3Provider,
- ZeroExConfig,
- MethodOpts,
- OrderTransactionOpts,
- TransactionOpts,
- LogEvent,
- DecodedLogEvent,
- EventWatcherCallback,
- OnOrderStateChangeCallback,
+ Order,
+ SignedOrder,
+ SignerType,
+ ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
-} from './types';
+ Token,
+ ERC20AssetData,
+ ERC721AssetData,
+ AssetProxyId,
+} from '@0xproject/types';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
- ContractEventArg,
LogWithDecodedArgs,
- Order,
- SignedOrder,
- ECSignature,
+ ContractEventArg,
+ Provider,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
-} from '@0xproject/types';
-
-export {
- EtherTokenContractEventArgs,
- WithdrawalContractEventArgs,
- DepositContractEventArgs,
- EtherTokenEvents,
-} from './contract_wrappers/generated/ether_token';
-
-export {
- TransferContractEventArgs,
- ApprovalContractEventArgs,
- TokenContractEventArgs,
- TokenEvents,
-} from './contract_wrappers/generated/token';
+} from 'ethereum-types';
export {
- LogErrorContractEventArgs,
- LogCancelContractEventArgs,
- LogFillContractEventArgs,
- ExchangeContractEventArgs,
- ExchangeEvents,
-} from './contract_wrappers/generated/exchange';
+ EventCallback,
+ ContractEvent,
+ IndexedFilterValues,
+ BlockRange,
+ OrderFillRequest,
+ ContractEventArgs,
+ MethodOpts,
+ OrderTransactionOpts,
+ TransactionOpts,
+ LogEvent,
+ DecodedLogEvent,
+ OnOrderStateChangeCallback,
+ ContractWrappersError,
+ WETH9Events,
+ WETH9WithdrawalEventArgs,
+ WETH9ApprovalEventArgs,
+ WETH9EventArgs,
+ WETH9DepositEventArgs,
+ WETH9TransferEventArgs,
+ ERC20TokenTransferEventArgs,
+ ERC20TokenApprovalEventArgs,
+ ERC20TokenEvents,
+ ERC20TokenEventArgs,
+ ERC721TokenApprovalEventArgs,
+ ERC721TokenApprovalForAllEventArgs,
+ ERC721TokenTransferEventArgs,
+ ERC721TokenEvents,
+ ExchangeCancelUpToEventArgs,
+ ExchangeAssetProxyRegisteredEventArgs,
+ ExchangeFillEventArgs,
+ ExchangeCancelEventArgs,
+ ExchangeEventArgs,
+ ContractWrappersConfig,
+ OrderInfo,
+} from '@0xproject/contract-wrappers';
diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/0x.js/src/order_watcher/event_watcher.ts
deleted file mode 100644
index 47bbd5b2e..000000000
--- a/packages/0x.js/src/order_watcher/event_watcher.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import { BlockParamLiteral, LogEntry } from '@0xproject/types';
-import { intervalUtils } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { EventWatcherCallback, ZeroExError } from '../types';
-import { assert } from '../utils/assert';
-
-const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
-
-enum LogEventState {
- Removed,
- Added,
-}
-
-/*
- * The EventWatcher watches for blockchain events at the specified block confirmation
- * depth.
- */
-export class EventWatcher {
- private _web3Wrapper: Web3Wrapper;
- private _pollingIntervalMs: number;
- private _intervalIdIfExists?: NodeJS.Timer;
- private _lastEvents: LogEntry[] = [];
- private _stateLayer: BlockParamLiteral;
- constructor(
- web3Wrapper: Web3Wrapper,
- pollingIntervalIfExistsMs: undefined | number,
- stateLayer: BlockParamLiteral = BlockParamLiteral.Latest,
- ) {
- this._web3Wrapper = web3Wrapper;
- this._stateLayer = stateLayer;
- this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs)
- ? DEFAULT_EVENT_POLLING_INTERVAL_MS
- : pollingIntervalIfExistsMs;
- }
- public subscribe(callback: EventWatcherCallback): void {
- assert.isFunction('callback', callback);
- if (!_.isUndefined(this._intervalIdIfExists)) {
- throw new Error(ZeroExError.SubscriptionAlreadyPresent);
- }
- this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
- this._pollForBlockchainEventsAsync.bind(this, callback),
- this._pollingIntervalMs,
- (err: Error) => {
- this.unsubscribe();
- callback(err);
- },
- );
- }
- public unsubscribe(): void {
- this._lastEvents = [];
- if (!_.isUndefined(this._intervalIdIfExists)) {
- intervalUtils.clearAsyncExcludingInterval(this._intervalIdIfExists);
- delete this._intervalIdIfExists;
- }
- }
- private async _pollForBlockchainEventsAsync(callback: EventWatcherCallback): Promise<void> {
- const pendingEvents = await this._getEventsAsync();
- if (_.isUndefined(pendingEvents)) {
- // HACK: This should never happen, but happens frequently on CI due to a ganache bug
- return;
- }
- if (pendingEvents.length === 0) {
- // HACK: Sometimes when node rebuilds the pending block we get back the empty result.
- // We don't want to emit a lot of removal events and bring them back after a couple of miliseconds,
- // that's why we just ignore those cases.
- return;
- }
- const removedEvents = _.differenceBy(this._lastEvents, pendingEvents, JSON.stringify);
- const newEvents = _.differenceBy(pendingEvents, this._lastEvents, JSON.stringify);
- await this._emitDifferencesAsync(removedEvents, LogEventState.Removed, callback);
- await this._emitDifferencesAsync(newEvents, LogEventState.Added, callback);
- this._lastEvents = pendingEvents;
- }
- private async _getEventsAsync(): Promise<LogEntry[]> {
- const eventFilter = {
- fromBlock: this._stateLayer,
- toBlock: this._stateLayer,
- };
- const events = await this._web3Wrapper.getLogsAsync(eventFilter);
- return events;
- }
- private async _emitDifferencesAsync(
- logs: LogEntry[],
- logEventState: LogEventState,
- callback: EventWatcherCallback,
- ): Promise<void> {
- for (const log of logs) {
- const logEvent = {
- removed: logEventState === LogEventState.Removed,
- ...log,
- };
- if (!_.isUndefined(this._intervalIdIfExists)) {
- callback(null, logEvent);
- }
- }
- }
-}
diff --git a/packages/0x.js/src/order_watcher/expiration_watcher.ts b/packages/0x.js/src/order_watcher/expiration_watcher.ts
deleted file mode 100644
index 00b62162d..000000000
--- a/packages/0x.js/src/order_watcher/expiration_watcher.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { BigNumber, intervalUtils } from '@0xproject/utils';
-import { RBTree } from 'bintrees';
-import * as _ from 'lodash';
-
-import { ZeroExError } from '../types';
-import { utils } from '../utils/utils';
-
-const DEFAULT_EXPIRATION_MARGIN_MS = 0;
-const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
-
-/**
- * This class includes the functionality to detect expired orders.
- * It stores them in a min heap by expiration time and checks for expired ones every `orderExpirationCheckingIntervalMs`
- */
-export class ExpirationWatcher {
- private _orderHashByExpirationRBTree: RBTree<string>;
- private _expiration: { [orderHash: string]: BigNumber } = {};
- private _orderExpirationCheckingIntervalMs: number;
- private _expirationMarginMs: number;
- private _orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
- constructor(expirationMarginIfExistsMs?: number, orderExpirationCheckingIntervalIfExistsMs?: number) {
- this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS;
- this._orderExpirationCheckingIntervalMs =
- expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
- const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
- const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
- this._orderHashByExpirationRBTree = new RBTree(comparator);
- }
- public subscribe(callback: (orderHash: string) => void): void {
- if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
- throw new Error(ZeroExError.SubscriptionAlreadyPresent);
- }
- this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval(
- this._pruneExpiredOrders.bind(this, callback),
- this._orderExpirationCheckingIntervalMs,
- _.noop, // _pruneExpiredOrders never throws
- );
- }
- public unsubscribe(): void {
- if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
- throw new Error(ZeroExError.SubscriptionNotFound);
- }
- intervalUtils.clearInterval(this._orderExpirationCheckingIntervalIdIfExists);
- delete this._orderExpirationCheckingIntervalIdIfExists;
- }
- public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
- this._expiration[orderHash] = expirationUnixTimestampMs;
- this._orderHashByExpirationRBTree.insert(orderHash);
- }
- public removeOrder(orderHash: string): void {
- this._orderHashByExpirationRBTree.remove(orderHash);
- delete this._expiration[orderHash];
- }
- private _pruneExpiredOrders(callback: (orderHash: string) => void): void {
- const currentUnixTimestampMs = utils.getCurrentUnixTimestampMs();
- while (true) {
- const hasTrakedOrders = this._orderHashByExpirationRBTree.size === 0;
- if (hasTrakedOrders) {
- break;
- }
- const nextOrderHashToExpire = this._orderHashByExpirationRBTree.min();
- const hasNoExpiredOrders = this._expiration[nextOrderHashToExpire].greaterThan(
- currentUnixTimestampMs.plus(this._expirationMarginMs),
- );
- const isSubscriptionActive = _.isUndefined(this._orderExpirationCheckingIntervalIdIfExists);
- if (hasNoExpiredOrders || isSubscriptionActive) {
- break;
- }
- const orderHash = this._orderHashByExpirationRBTree.min();
- this._orderHashByExpirationRBTree.remove(orderHash);
- delete this._expiration[orderHash];
- callback(orderHash);
- }
- }
-}
diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/0x.js/src/order_watcher/order_state_watcher.ts
deleted file mode 100644
index cd6016c5a..000000000
--- a/packages/0x.js/src/order_watcher/order_state_watcher.ts
+++ /dev/null
@@ -1,384 +0,0 @@
-import { schemas } from '@0xproject/json-schemas';
-import { BlockParamLiteral, LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
-import { AbiDecoder, intervalUtils } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { ZeroEx } from '../0x';
-import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
-import {
- DepositContractEventArgs,
- EtherTokenEvents,
- WithdrawalContractEventArgs,
-} from '../contract_wrappers/generated/ether_token';
-import {
- ExchangeEvents,
- LogCancelContractEventArgs,
- LogFillContractEventArgs,
-} from '../contract_wrappers/generated/exchange';
-import {
- ApprovalContractEventArgs,
- TokenEvents,
- TransferContractEventArgs,
-} from '../contract_wrappers/generated/token';
-import { TokenWrapper } from '../contract_wrappers/token_wrapper';
-import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
-import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
-import {
- ContractEventArgs,
- ExchangeContractErrs,
- LogEvent,
- OnOrderStateChangeCallback,
- OrderState,
- OrderStateWatcherConfig,
- ZeroExError,
-} from '../types';
-import { assert } from '../utils/assert';
-import { OrderStateUtils } from '../utils/order_state_utils';
-import { utils } from '../utils/utils';
-
-import { EventWatcher } from './event_watcher';
-import { ExpirationWatcher } from './expiration_watcher';
-
-interface DependentOrderHashes {
- [makerAddress: string]: {
- [makerToken: string]: Set<string>;
- };
-}
-
-interface OrderByOrderHash {
- [orderHash: string]: SignedOrder;
-}
-
-interface OrderStateByOrderHash {
- [orderHash: string]: OrderState;
-}
-
-const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h
-
-/**
- * This class includes all the functionality related to watching a set of orders
- * for potential changes in order validity/fillability. The orderWatcher notifies
- * the subscriber of these changes so that a final decision can be made on whether
- * the order should be deemed invalid.
- */
-export class OrderStateWatcher {
- private _orderStateByOrderHashCache: OrderStateByOrderHash = {};
- private _orderByOrderHash: OrderByOrderHash = {};
- private _dependentOrderHashes: DependentOrderHashes = {};
- private _callbackIfExists?: OnOrderStateChangeCallback;
- private _eventWatcher: EventWatcher;
- private _web3Wrapper: Web3Wrapper;
- private _abiDecoder: AbiDecoder;
- private _expirationWatcher: ExpirationWatcher;
- private _orderStateUtils: OrderStateUtils;
- private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
- private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
- private _cleanupJobInterval: number;
- private _cleanupJobIntervalIdIfExists?: NodeJS.Timer;
- constructor(
- web3Wrapper: Web3Wrapper,
- abiDecoder: AbiDecoder,
- token: TokenWrapper,
- exchange: ExchangeWrapper,
- config?: OrderStateWatcherConfig,
- ) {
- this._abiDecoder = abiDecoder;
- this._web3Wrapper = web3Wrapper;
- const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
- const stateLayer =
- _.isUndefined(config) || _.isUndefined(config.stateLayer) ? BlockParamLiteral.Latest : config.stateLayer;
- this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs, stateLayer);
- this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token, stateLayer);
- this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
- this._orderStateUtils = new OrderStateUtils(
- this._balanceAndProxyAllowanceLazyStore,
- this._orderFilledCancelledLazyStore,
- );
- const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config)
- ? undefined
- : config.orderExpirationCheckingIntervalMs;
- const expirationMarginIfExistsMs = _.isUndefined(config) ? undefined : config.expirationMarginMs;
- this._expirationWatcher = new ExpirationWatcher(
- expirationMarginIfExistsMs,
- orderExpirationCheckingIntervalMsIfExists,
- );
- this._cleanupJobInterval =
- _.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs)
- ? DEFAULT_CLEANUP_JOB_INTERVAL_MS
- : config.cleanupJobIntervalMs;
- }
- /**
- * Add an order to the orderStateWatcher. Before the order is added, it's
- * signature is verified.
- * @param signedOrder The order you wish to start watching.
- */
- public addOrder(signedOrder: SignedOrder): void {
- assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
- this._orderByOrderHash[orderHash] = signedOrder;
- this._addToDependentOrderHashes(signedOrder, orderHash);
- const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(1000);
- this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs);
- }
- /**
- * Removes an order from the orderStateWatcher
- * @param orderHash The orderHash of the order you wish to stop watching.
- */
- public removeOrder(orderHash: string): void {
- assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
- const signedOrder = this._orderByOrderHash[orderHash];
- if (_.isUndefined(signedOrder)) {
- return; // noop
- }
- delete this._orderByOrderHash[orderHash];
- delete this._orderStateByOrderHashCache[orderHash];
- const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
- const zrxTokenAddress = exchange.getZRXTokenAddress();
-
- this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
- if (zrxTokenAddress !== signedOrder.makerTokenAddress) {
- this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
- }
-
- this._expirationWatcher.removeOrder(orderHash);
- }
- /**
- * Starts an orderStateWatcher subscription. The callback will be called every time a watched order's
- * backing blockchain state has changed. This is a call-to-action for the caller to re-validate the order.
- * @param callback Receives the orderHash of the order that should be re-validated, together
- * with all the order-relevant blockchain state needed to re-validate the order.
- */
- public subscribe(callback: OnOrderStateChangeCallback): void {
- assert.isFunction('callback', callback);
- if (!_.isUndefined(this._callbackIfExists)) {
- throw new Error(ZeroExError.SubscriptionAlreadyPresent);
- }
- this._callbackIfExists = callback;
- this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this));
- this._expirationWatcher.subscribe(this._onOrderExpired.bind(this));
- this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
- this._cleanupAsync.bind(this),
- this._cleanupJobInterval,
- (err: Error) => {
- this.unsubscribe();
- callback(err);
- },
- );
- }
- /**
- * Ends an orderStateWatcher subscription.
- */
- public unsubscribe(): void {
- if (_.isUndefined(this._callbackIfExists) || _.isUndefined(this._cleanupJobIntervalIdIfExists)) {
- throw new Error(ZeroExError.SubscriptionNotFound);
- }
- this._balanceAndProxyAllowanceLazyStore.deleteAll();
- this._orderFilledCancelledLazyStore.deleteAll();
- delete this._callbackIfExists;
- this._eventWatcher.unsubscribe();
- this._expirationWatcher.unsubscribe();
- intervalUtils.clearAsyncExcludingInterval(this._cleanupJobIntervalIdIfExists);
- }
- private async _cleanupAsync(): Promise<void> {
- for (const orderHash of _.keys(this._orderByOrderHash)) {
- this._cleanupOrderRelatedState(orderHash);
- await this._emitRevalidateOrdersAsync([orderHash]);
- }
- }
- private _cleanupOrderRelatedState(orderHash: string): void {
- const signedOrder = this._orderByOrderHash[orderHash];
-
- this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(orderHash);
- this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(orderHash);
-
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.makerTokenAddress, signedOrder.maker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(signedOrder.makerTokenAddress, signedOrder.maker);
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.takerTokenAddress, signedOrder.taker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(signedOrder.takerTokenAddress, signedOrder.taker);
-
- const zrxTokenAddress = this._getZRXTokenAddress();
- if (!signedOrder.makerFee.isZero()) {
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.maker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.maker);
- }
- if (!signedOrder.takerFee.isZero()) {
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.taker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.taker);
- }
- }
- private _onOrderExpired(orderHash: string): void {
- const orderState: OrderState = {
- isValid: false,
- orderHash,
- error: ExchangeContractErrs.OrderFillExpired,
- };
- if (!_.isUndefined(this._orderByOrderHash[orderHash])) {
- this.removeOrder(orderHash);
- if (!_.isUndefined(this._callbackIfExists)) {
- this._callbackIfExists(null, orderState);
- }
- }
- }
- private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEvent): Promise<void> {
- if (!_.isNull(err)) {
- if (!_.isUndefined(this._callbackIfExists)) {
- this._callbackIfExists(err);
- this.unsubscribe();
- }
- return;
- }
- const log = logIfExists as LogEvent; // At this moment we are sure that no error occured and log is defined.
- const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(log);
- const isLogDecoded = !_.isUndefined(((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event);
- if (!isLogDecoded) {
- return; // noop
- }
- const decodedLog = (maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>;
- let makerToken: string;
- let makerAddress: string;
- switch (decodedLog.event) {
- case TokenEvents.Approval: {
- // Invalidate cache
- const args = decodedLog.args as ApprovalContractEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(decodedLog.address, args._owner);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
- break;
- }
- case TokenEvents.Transfer: {
- // Invalidate cache
- const args = decodedLog.args as TransferContractEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._from);
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._to);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._from;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
- break;
- }
- case EtherTokenEvents.Deposit: {
- // Invalidate cache
- const args = decodedLog.args as DepositContractEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
- break;
- }
- case EtherTokenEvents.Withdrawal: {
- // Invalidate cache
- const args = decodedLog.args as WithdrawalContractEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
- break;
- }
- case ExchangeEvents.LogFill: {
- // Invalidate cache
- const args = decodedLog.args as LogFillContractEventArgs;
- this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
- // Revalidate orders
- const orderHash = args.orderHash;
- const isOrderWatched = !_.isUndefined(this._orderByOrderHash[orderHash]);
- if (isOrderWatched) {
- await this._emitRevalidateOrdersAsync([orderHash]);
- }
- break;
- }
- case ExchangeEvents.LogCancel: {
- // Invalidate cache
- const args = decodedLog.args as LogCancelContractEventArgs;
- this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(args.orderHash);
- // Revalidate orders
- const orderHash = args.orderHash;
- const isOrderWatched = !_.isUndefined(this._orderByOrderHash[orderHash]);
- if (isOrderWatched) {
- await this._emitRevalidateOrdersAsync([orderHash]);
- }
- break;
- }
- case ExchangeEvents.LogError:
- return; // noop
-
- default:
- throw utils.spawnSwitchErr('decodedLog.event', decodedLog.event);
- }
- }
- private async _emitRevalidateOrdersAsync(orderHashes: string[]): Promise<void> {
- for (const orderHash of orderHashes) {
- const signedOrder = this._orderByOrderHash[orderHash];
- // Most of these calls will never reach the network because the data is fetched from stores
- // and only updated when cache is invalidated
- const orderState = await this._orderStateUtils.getOrderStateAsync(signedOrder);
- if (_.isUndefined(this._callbackIfExists)) {
- break; // Unsubscribe was called
- }
- if (_.isEqual(orderState, this._orderStateByOrderHashCache[orderHash])) {
- // Actual order state didn't change
- continue;
- } else {
- this._orderStateByOrderHashCache[orderHash] = orderState;
- }
- this._callbackIfExists(null, orderState);
- }
- }
- private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
- if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
- this._dependentOrderHashes[signedOrder.maker] = {};
- }
- if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress])) {
- this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set();
- }
- this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash);
- const zrxTokenAddress = this._getZRXTokenAddress();
- if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress])) {
- this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress] = new Set();
- }
- this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress].add(orderHash);
- }
- private _removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string) {
- this._dependentOrderHashes[makerAddress][tokenAddress].delete(orderHash);
- if (this._dependentOrderHashes[makerAddress][tokenAddress].size === 0) {
- delete this._dependentOrderHashes[makerAddress][tokenAddress];
- }
- if (_.isEmpty(this._dependentOrderHashes[makerAddress])) {
- delete this._dependentOrderHashes[makerAddress];
- }
- }
- private _getZRXTokenAddress(): string {
- const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
- const zrxTokenAddress = exchange.getZRXTokenAddress();
- return zrxTokenAddress;
- }
-}
diff --git a/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts b/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts
deleted file mode 100644
index 184c13aa4..000000000
--- a/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-
-export class RemainingFillableCalculator {
- private _signedOrder: SignedOrder;
- private _isMakerTokenZRX: boolean;
- // Transferrable Amount is the minimum of Approval and Balance
- private _transferrableMakerTokenAmount: BigNumber;
- private _transferrableMakerFeeTokenAmount: BigNumber;
- private _remainingMakerTokenAmount: BigNumber;
- private _remainingMakerFeeAmount: BigNumber;
- constructor(
- signedOrder: SignedOrder,
- isMakerTokenZRX: boolean,
- transferrableMakerTokenAmount: BigNumber,
- transferrableMakerFeeTokenAmount: BigNumber,
- remainingMakerTokenAmount: BigNumber,
- ) {
- this._signedOrder = signedOrder;
- this._isMakerTokenZRX = isMakerTokenZRX;
- this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
- this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
- this._remainingMakerTokenAmount = remainingMakerTokenAmount;
- this._remainingMakerFeeAmount = remainingMakerTokenAmount
- .times(signedOrder.makerFee)
- .dividedToIntegerBy(signedOrder.makerTokenAmount);
- }
- public computeRemainingMakerFillable(): BigNumber {
- if (this._hasSufficientFundsForFeeAndTransferAmount()) {
- return this._remainingMakerTokenAmount;
- }
- if (this._signedOrder.makerFee.isZero()) {
- return BigNumber.min(this._remainingMakerTokenAmount, this._transferrableMakerTokenAmount);
- }
- return this._calculatePartiallyFillableMakerTokenAmount();
- }
- public computeRemainingTakerFillable(): BigNumber {
- return this.computeRemainingMakerFillable()
- .times(this._signedOrder.takerTokenAmount)
- .dividedToIntegerBy(this._signedOrder.makerTokenAmount);
- }
- private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
- if (this._isMakerTokenZRX) {
- const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
- const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
- totalZRXTransferAmountRequired,
- );
- return hasSufficientFunds;
- } else {
- const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
- this._remainingMakerTokenAmount,
- );
- const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
- this._remainingMakerFeeAmount,
- );
- const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
- return hasSufficientFunds;
- }
- }
- private _calculatePartiallyFillableMakerTokenAmount(): BigNumber {
- // Given an order for 200 wei for 2 ZRXwei fee, find 100 wei for 1 ZRXwei. Order ratio is then 100:1
- const orderToFeeRatio = this._signedOrder.makerTokenAmount.dividedBy(this._signedOrder.makerFee);
- // The number of times the maker can fill the order, if each fill only required the transfer of a single
- // baseUnit of fee tokens.
- // Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
- const fillableTimesInFeeTokenBaseUnits = BigNumber.min(
- this._transferrableMakerFeeTokenAmount,
- this._remainingMakerFeeAmount,
- );
- // The number of times the Maker can fill the order, given the Maker Token Balance
- // Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, maker can fill this order 1 time.
- let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
- if (this._isMakerTokenZRX) {
- // If ZRX is the maker token, the Fee and the Maker amount need to be removed from the same pool;
- // 200 ZRXwei for 2ZRXwei fee can only be filled once (need 202 ZRXwei)
- const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
- // The purchasing power here is less as the tokens are taken from the same Pool
- // For every one number of fills, we have to take an extra ZRX out of the pool
- fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(orderToFeeRatio.plus(new BigNumber(1)));
- }
- // When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
- // This can result in a RoundingError being thrown by the Exchange Contract.
- const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
- .times(this._signedOrder.makerTokenAmount)
- .dividedToIntegerBy(this._signedOrder.makerFee);
- const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
- .times(this._signedOrder.makerTokenAmount)
- .dividedToIntegerBy(this._signedOrder.makerFee);
- const partiallyFillableAmount = BigNumber.min(
- partiallyFillableMakerTokenAmount,
- partiallyFillableFeeTokenAmount,
- );
- return partiallyFillableAmount;
- }
-}
diff --git a/packages/0x.js/src/schemas/zero_ex_private_network_config_schema.ts b/packages/0x.js/src/schemas/zero_ex_private_network_config_schema.ts
index f7f649a6d..378b86e77 100644
--- a/packages/0x.js/src/schemas/zero_ex_private_network_config_schema.ts
+++ b/packages/0x.js/src/schemas/zero_ex_private_network_config_schema.ts
@@ -8,8 +8,8 @@ export const zeroExPrivateNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
- tokenRegistryContractAddress: { $ref: '/Address' },
- tokenTransferProxyContractAddress: { $ref: '/Address' },
+ erc20ProxyContractAddress: { $ref: '/Address' },
+ erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
@@ -29,7 +29,7 @@ export const zeroExPrivateNetworkConfigSchema = {
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
- 'tokenRegistryContractAddress',
- 'tokenTransferProxyContractAddress',
+ 'erc20ProxyContractAddress',
+ 'erc721ProxyContractAddress',
],
};
diff --git a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts
index 9da31481a..f2a9a4d56 100644
--- a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts
+++ b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts
@@ -1,15 +1,29 @@
+const networkNameToId: { [networkName: string]: number } = {
+ mainnet: 1,
+ ropsten: 3,
+ rinkeby: 4,
+ kovan: 42,
+ ganache: 50,
+};
+
export const zeroExPublicNetworkConfigSchema = {
id: '/ZeroExPublicNetworkConfig',
properties: {
networkId: {
type: 'number',
- enum: [1, 3, 4, 42, 50],
+ enum: [
+ networkNameToId.mainnet,
+ networkNameToId.ropsten,
+ networkNameToId.rinkeby,
+ networkNameToId.kovan,
+ networkNameToId.ganache,
+ ],
},
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
- tokenRegistryContractAddress: { $ref: '/Address' },
- tokenTransferProxyContractAddress: { $ref: '/Address' },
+ erc20ProxyContractAddress: { $ref: '/Address' },
+ erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
diff --git a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts b/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts
deleted file mode 100644
index ede1319fe..000000000
--- a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { TokenWrapper } from '../contract_wrappers/token_wrapper';
-
-/**
- * Copy on read store for balances/proxyAllowances of tokens/accounts
- */
-export class BalanceAndProxyAllowanceLazyStore {
- private _token: TokenWrapper;
- private _defaultBlock: BlockParamLiteral;
- private _balance: {
- [tokenAddress: string]: {
- [userAddress: string]: BigNumber;
- };
- };
- private _proxyAllowance: {
- [tokenAddress: string]: {
- [userAddress: string]: BigNumber;
- };
- };
- constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
- this._token = token;
- this._defaultBlock = defaultBlock;
- this._balance = {};
- this._proxyAllowance = {};
- }
- public async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
- if (_.isUndefined(this._balance[tokenAddress]) || _.isUndefined(this._balance[tokenAddress][userAddress])) {
- const methodOpts = {
- defaultBlock: this._defaultBlock,
- };
- const balance = await this._token.getBalanceAsync(tokenAddress, userAddress, methodOpts);
- this.setBalance(tokenAddress, userAddress, balance);
- }
- const cachedBalance = this._balance[tokenAddress][userAddress];
- return cachedBalance;
- }
- public setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void {
- if (_.isUndefined(this._balance[tokenAddress])) {
- this._balance[tokenAddress] = {};
- }
- this._balance[tokenAddress][userAddress] = balance;
- }
- public deleteBalance(tokenAddress: string, userAddress: string): void {
- if (!_.isUndefined(this._balance[tokenAddress])) {
- delete this._balance[tokenAddress][userAddress];
- if (_.isEmpty(this._balance[tokenAddress])) {
- delete this._balance[tokenAddress];
- }
- }
- }
- public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
- if (
- _.isUndefined(this._proxyAllowance[tokenAddress]) ||
- _.isUndefined(this._proxyAllowance[tokenAddress][userAddress])
- ) {
- const methodOpts = {
- defaultBlock: this._defaultBlock,
- };
- const proxyAllowance = await this._token.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
- this.setProxyAllowance(tokenAddress, userAddress, proxyAllowance);
- }
- const cachedProxyAllowance = this._proxyAllowance[tokenAddress][userAddress];
- return cachedProxyAllowance;
- }
- public setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void {
- if (_.isUndefined(this._proxyAllowance[tokenAddress])) {
- this._proxyAllowance[tokenAddress] = {};
- }
- this._proxyAllowance[tokenAddress][userAddress] = proxyAllowance;
- }
- public deleteProxyAllowance(tokenAddress: string, userAddress: string): void {
- if (!_.isUndefined(this._proxyAllowance[tokenAddress])) {
- delete this._proxyAllowance[tokenAddress][userAddress];
- if (_.isEmpty(this._proxyAllowance[tokenAddress])) {
- delete this._proxyAllowance[tokenAddress];
- }
- }
- }
- public deleteAll(): void {
- this._balance = {};
- this._proxyAllowance = {};
- }
-}
diff --git a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts b/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts
deleted file mode 100644
index 0a0d93406..000000000
--- a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
-
-/**
- * Copy on read store for filled/cancelled taker amounts
- */
-export class OrderFilledCancelledLazyStore {
- private _exchange: ExchangeWrapper;
- private _filledTakerAmount: {
- [orderHash: string]: BigNumber;
- };
- private _cancelledTakerAmount: {
- [orderHash: string]: BigNumber;
- };
- constructor(exchange: ExchangeWrapper) {
- this._exchange = exchange;
- this._filledTakerAmount = {};
- this._cancelledTakerAmount = {};
- }
- public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
- if (_.isUndefined(this._filledTakerAmount[orderHash])) {
- const methodOpts = {
- defaultBlock: BlockParamLiteral.Pending,
- };
- const filledTakerAmount = await this._exchange.getFilledTakerAmountAsync(orderHash, methodOpts);
- this.setFilledTakerAmount(orderHash, filledTakerAmount);
- }
- const cachedFilled = this._filledTakerAmount[orderHash];
- return cachedFilled;
- }
- public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void {
- this._filledTakerAmount[orderHash] = filledTakerAmount;
- }
- public deleteFilledTakerAmount(orderHash: string): void {
- delete this._filledTakerAmount[orderHash];
- }
- public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
- if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
- const methodOpts = {
- defaultBlock: BlockParamLiteral.Pending,
- };
- const cancelledTakerAmount = await this._exchange.getCancelledTakerAmountAsync(orderHash, methodOpts);
- this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
- }
- const cachedCancelled = this._cancelledTakerAmount[orderHash];
- return cachedCancelled;
- }
- public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void {
- this._cancelledTakerAmount[orderHash] = cancelledTakerAmount;
- }
- public deleteCancelledTakerAmount(orderHash: string): void {
- delete this._cancelledTakerAmount[orderHash];
- }
- public deleteAll(): void {
- this._filledTakerAmount = {};
- this._cancelledTakerAmount = {};
- }
-}
diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts
index 7f1f140ca..651b15abd 100644
--- a/packages/0x.js/src/types.ts
+++ b/packages/0x.js/src/types.ts
@@ -1,286 +1,7 @@
-import { BigNumber } from '@0xproject/utils';
-
-import {
- BlockParam,
- BlockParamLiteral,
- ContractAbi,
- ContractEventArg,
- FilterObject,
- LogEntryEvent,
- LogWithDecodedArgs,
- Order,
- SignedOrder,
-} from '@0xproject/types';
-
-import * as Web3 from 'web3';
-
-import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
-import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
-import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
-
-export enum ZeroExError {
- ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
- ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
- EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST',
- TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST',
- TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST',
- TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
- UnhandledError = 'UNHANDLED_ERROR',
- UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
- InvalidSignature = 'INVALID_SIGNATURE',
- ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
- InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
- InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
- InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
- InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
- InvalidJump = 'INVALID_JUMP',
- OutOfGas = 'OUT_OF_GAS',
- NoNetworkId = 'NO_NETWORK_ID',
- SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
- SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
- TransactionMiningTimeout = 'TRANSACTION_MINING_TIMEOUT',
-}
-
export enum InternalZeroExError {
NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
}
-export type OrderAddresses = [string, string, string, string, string];
-
-export type OrderValues = [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber];
-
-export type LogEvent = LogEntryEvent;
-export interface DecodedLogEvent<ArgsType> {
- isRemoved: boolean;
- log: LogWithDecodedArgs<ArgsType>;
-}
-
-export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
-export type EventWatcherCallback = (err: null | Error, log?: LogEvent) => void;
-
-export enum ExchangeContractErrCodes {
- ERROR_FILL_EXPIRED, // Order has already expired
- ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled
- ERROR_FILL_TRUNCATION, // Rounding error too large
- ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer
- ERROR_CANCEL_EXPIRED, // Order has already expired
- ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled
-}
-
-export enum ExchangeContractErrs {
- OrderFillExpired = 'ORDER_FILL_EXPIRED',
- OrderCancelExpired = 'ORDER_CANCEL_EXPIRED',
- OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO',
- OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED',
- OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO',
- OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO',
- OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR',
- FillBalanceAllowanceError = 'FILL_BALANCE_ALLOWANCE_ERROR',
- InsufficientTakerBalance = 'INSUFFICIENT_TAKER_BALANCE',
- InsufficientTakerAllowance = 'INSUFFICIENT_TAKER_ALLOWANCE',
- InsufficientMakerBalance = 'INSUFFICIENT_MAKER_BALANCE',
- InsufficientMakerAllowance = 'INSUFFICIENT_MAKER_ALLOWANCE',
- InsufficientTakerFeeBalance = 'INSUFFICIENT_TAKER_FEE_BALANCE',
- InsufficientTakerFeeAllowance = 'INSUFFICIENT_TAKER_FEE_ALLOWANCE',
- InsufficientMakerFeeBalance = 'INSUFFICIENT_MAKER_FEE_BALANCE',
- InsufficientMakerFeeAllowance = 'INSUFFICIENT_MAKER_FEE_ALLOWANCE',
- TransactionSenderIsNotFillOrderTaker = 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER',
- MultipleMakersInSingleCancelBatchDisallowed = 'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED',
- InsufficientRemainingFillAmount = 'INSUFFICIENT_REMAINING_FILL_AMOUNT',
- MultipleTakerTokensInFillUpToDisallowed = 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED',
- BatchOrdersMustHaveSameExchangeAddress = 'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS',
- BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM',
-}
-
-export interface ContractEvent {
- logIndex: number;
- transactionIndex: number;
- transactionHash: string;
- blockHash: string;
- blockNumber: number;
- address: string;
- type: string;
- event: string;
- args: ContractEventArgs;
-}
-
-export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
-
-// [address, name, symbol, decimals, ipfsHash, swarmHash]
-export type TokenMetadata = [string, string, string, number, string, string];
-
-export interface Token {
- name: string;
- address: string;
- symbol: string;
- decimals: number;
-}
-
-export interface TxOpts {
- from: string;
- gas?: number;
- value?: BigNumber;
- gasPrice?: BigNumber;
-}
-
-export interface TokenAddressBySymbol {
- [symbol: string]: string;
-}
-
-export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
-
-export interface IndexedFilterValues {
- [index: string]: ContractEventArg;
-}
-
-export interface BlockRange {
- fromBlock: BlockParam;
- toBlock: BlockParam;
-}
-
-export type DoneCallback = (err?: Error) => void;
-
-export interface OrderCancellationRequest {
- order: Order | SignedOrder;
- takerTokenCancelAmount: BigNumber;
-}
-
-export interface OrderFillRequest {
- signedOrder: SignedOrder;
- takerTokenFillAmount: BigNumber;
-}
-
-export type AsyncMethod = (...args: any[]) => Promise<any>;
-export type SyncMethod = (...args: any[]) => any;
-
-/**
- * We re-export the `Web3.Provider` type specified in the Web3 Typescript typings
- * since it is the type of the `provider` argument to the `ZeroEx` constructor.
- * It is however a `Web3` library type, not a native `0x.js` type. To learn more
- * about providers, visit https://0xproject.com/wiki#Web3-Provider-Explained
- */
-export type Web3Provider = Web3.Provider;
-
-/*
- * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default: 50
- * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Default: 200
- * expirationMarginMs: Amount of time before order expiry that you'd like to be notified
- * of an orders expiration. Default: 0
- * cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Defaults: 1h
- * stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default: latest
- */
-export interface OrderStateWatcherConfig {
- orderExpirationCheckingIntervalMs?: number;
- eventPollingIntervalMs?: number;
- expirationMarginMs?: number;
- cleanupJobIntervalMs?: number;
- stateLayer: BlockParamLiteral;
-}
-
-/*
- * networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc)
- * gasPrice: Gas price to use with every transaction
- * exchangeContractAddress: The address of an exchange contract to use
- * zrxContractAddress: The address of the ZRX contract to use
- * tokenRegistryContractAddress: The address of a token registry contract to use
- * tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
- * orderWatcherConfig: All the configs related to the orderWatcher
- */
-export interface ZeroExConfig {
- networkId: number;
- gasPrice?: BigNumber;
- exchangeContractAddress?: string;
- zrxContractAddress?: string;
- tokenRegistryContractAddress?: string;
- tokenTransferProxyContractAddress?: string;
- orderWatcherConfig?: OrderStateWatcherConfig;
-}
-
-export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken';
-
-export interface Artifact {
- contract_name: ArtifactContractName;
- abi: ContractAbi;
- networks: {
- [networkId: number]: {
- address: string;
- };
- };
-}
-
-/*
- * expectedFillTakerTokenAmount: If specified, the validation method will ensure that the
- * supplied order maker has a sufficient allowance/balance to fill this amount of the order's
- * takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient
- * allowance/balance to fill the entire remaining order amount.
- */
-export interface ValidateOrderFillableOpts {
- expectedFillTakerTokenAmount?: BigNumber;
-}
-
-/*
- * defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number
- * let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the
- * backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive`
- * flag when running Parity).
- */
-export interface MethodOpts {
- defaultBlock?: BlockParam;
-}
-
-/*
- * gasPrice: Gas price in Wei to use for a transaction
- * gasLimit: The amount of gas to send with a transaction
- */
-export interface TransactionOpts {
- gasPrice?: BigNumber;
- gasLimit?: number;
-}
-
-/*
- * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before
- * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default: true
- */
-export interface OrderTransactionOpts extends TransactionOpts {
- shouldValidate?: boolean;
-}
-
-export enum TradeSide {
- Maker = 'maker',
- Taker = 'taker',
-}
-
-export enum TransferType {
- Trade = 'trade',
- Fee = 'fee',
-}
-
-export interface OrderRelevantState {
- makerBalance: BigNumber;
- makerProxyAllowance: BigNumber;
- makerFeeBalance: BigNumber;
- makerFeeProxyAllowance: BigNumber;
- filledTakerTokenAmount: BigNumber;
- cancelledTakerTokenAmount: BigNumber;
- remainingFillableMakerTokenAmount: BigNumber;
- remainingFillableTakerTokenAmount: BigNumber;
-}
-
-export interface OrderStateValid {
- isValid: true;
- orderHash: string;
- orderRelevantState: OrderRelevantState;
-}
-
-export interface OrderStateInvalid {
- isValid: false;
- orderHash: string;
- error: ExchangeContractErrs;
-}
-
-export type OrderState = OrderStateValid | OrderStateInvalid;
-
-export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
// tslint:disable:max-file-line-count
diff --git a/packages/0x.js/src/utils/assert.ts b/packages/0x.js/src/utils/assert.ts
deleted file mode 100644
index 5e8004cd0..000000000
--- a/packages/0x.js/src/utils/assert.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { assert as sharedAssert } from '@0xproject/assert';
-// We need those two unused imports because they're actually used by sharedAssert which gets injected here
-// tslint:disable-next-line:no-unused-variable
-import { Schema } from '@0xproject/json-schemas';
-// tslint:disable-next-line:no-unused-variable
-import { ECSignature } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as _ from 'lodash';
-
-import { signatureUtils } from '../utils/signature_utils';
-
-export const assert = {
- ...sharedAssert,
- isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) {
- const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
- this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
- },
- async isSenderAddressAsync(
- variableName: string,
- senderAddressHex: string,
- web3Wrapper: Web3Wrapper,
- ): Promise<void> {
- sharedAssert.isETHAddressHex(variableName, senderAddressHex);
- const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
- sharedAssert.assert(
- isSenderAddressAvailable,
- `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
- );
- },
- async isUserAddressAvailableAsync(web3Wrapper: Web3Wrapper): Promise<void> {
- const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
- this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 provider');
- },
-};
diff --git a/packages/0x.js/src/utils/constants.ts b/packages/0x.js/src/utils/constants.ts
index 06beec8e2..5a5ba0e0a 100644
--- a/packages/0x.js/src/utils/constants.ts
+++ b/packages/0x.js/src/utils/constants.ts
@@ -1,12 +1,4 @@
-import { BigNumber } from '@0xproject/utils';
-
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
TESTRPC_NETWORK_ID: 50,
- MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
- INVALID_JUMP_PATTERN: 'invalid JUMP at',
- OUT_OF_GAS_PATTERN: 'out of gas',
- INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
- UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
- DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
};
diff --git a/packages/0x.js/src/utils/decorators.ts b/packages/0x.js/src/utils/decorators.ts
deleted file mode 100644
index f774d734e..000000000
--- a/packages/0x.js/src/utils/decorators.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import * as _ from 'lodash';
-
-import { AsyncMethod, SyncMethod, ZeroExError } from '../types';
-
-import { constants } from './constants';
-
-type ErrorTransformer = (err: Error) => Error;
-
-const contractCallErrorTransformer = (error: Error) => {
- if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) {
- return new Error(ZeroExError.InvalidJump);
- }
- if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) {
- return new Error(ZeroExError.OutOfGas);
- }
- return error;
-};
-
-const schemaErrorTransformer = (error: Error) => {
- if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
- const errMsg =
- 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
- return new Error(errMsg);
- }
- return error;
-};
-
-/**
- * Source: https://stackoverflow.com/a/29837695/3546986
- */
-const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
- const asyncErrorHandlingDecorator = (
- target: object,
- key: string | symbol,
- descriptor: TypedPropertyDescriptor<AsyncMethod>,
- ) => {
- const originalMethod = descriptor.value as AsyncMethod;
-
- // Do not use arrow syntax here. Use a function expression in
- // order to use the correct value of `this` in this method
- // tslint:disable-next-line:only-arrow-functions
- descriptor.value = async function(...args: any[]) {
- try {
- const result = await originalMethod.apply(this, args);
- return result;
- } catch (error) {
- const transformedError = errorTransformer(error);
- throw transformedError;
- }
- };
-
- return descriptor;
- };
-
- return asyncErrorHandlingDecorator;
-};
-
-const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
- const syncErrorHandlingDecorator = (
- target: object,
- key: string | symbol,
- descriptor: TypedPropertyDescriptor<SyncMethod>,
- ) => {
- const originalMethod = descriptor.value as SyncMethod;
-
- // Do not use arrow syntax here. Use a function expression in
- // order to use the correct value of `this` in this method
- // tslint:disable-next-line:only-arrow-functions
- descriptor.value = function(...args: any[]) {
- try {
- const result = originalMethod.apply(this, args);
- return result;
- } catch (error) {
- const transformedError = errorTransformer(error);
- throw transformedError;
- }
- };
-
- return descriptor;
- };
-
- return syncErrorHandlingDecorator;
-};
-
-// _.flow(f, g) = f ∘ g
-const zeroExErrorTransformer = _.flow(schemaErrorTransformer, contractCallErrorTransformer);
-
-export const decorators = {
- asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer),
- syncZeroExErrorHandler: syncErrorHandlerFactory(zeroExErrorTransformer),
-};
diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/0x.js/src/utils/exchange_transfer_simulator.ts
deleted file mode 100644
index 9a920c643..000000000
--- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { TokenWrapper } from '../contract_wrappers/token_wrapper';
-import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
-import { ExchangeContractErrs, TradeSide, TransferType } from '../types';
-
-enum FailureReason {
- Balance = 'balance',
- ProxyAllowance = 'proxyAllowance',
-}
-
-const ERR_MSG_MAPPING = {
- [FailureReason.Balance]: {
- [TradeSide.Maker]: {
- [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerBalance,
- [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeBalance,
- },
- [TradeSide.Taker]: {
- [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerBalance,
- [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeBalance,
- },
- },
- [FailureReason.ProxyAllowance]: {
- [TradeSide.Maker]: {
- [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerAllowance,
- [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeAllowance,
- },
- [TradeSide.Taker]: {
- [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerAllowance,
- [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeAllowance,
- },
- },
-};
-
-export class ExchangeTransferSimulator {
- private _store: BalanceAndProxyAllowanceLazyStore;
- private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
- private static _throwValidationError(
- failureReason: FailureReason,
- tradeSide: TradeSide,
- transferType: TransferType,
- ): never {
- const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
- throw new Error(errMsg);
- }
- constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
- this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock);
- this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
- }
- /**
- * Simulates transferFrom call performed by a proxy
- * @param tokenAddress Address of the token to be transferred
- * @param from Owner of the transferred tokens
- * @param to Recipient of the transferred tokens
- * @param amountInBaseUnits The amount of tokens being transferred
- * @param tradeSide Is Maker/Taker transferring
- * @param transferType Is it a fee payment or a value transfer
- */
- public async transferFromAsync(
- tokenAddress: string,
- from: string,
- to: string,
- amountInBaseUnits: BigNumber,
- tradeSide: TradeSide,
- transferType: TransferType,
- ): Promise<void> {
- const balance = await this._store.getBalanceAsync(tokenAddress, from);
- const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
- if (proxyAllowance.lessThan(amountInBaseUnits)) {
- ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
- }
- if (balance.lessThan(amountInBaseUnits)) {
- ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType);
- }
- await this._decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits);
- await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
- await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
- }
- private async _decreaseProxyAllowanceAsync(
- tokenAddress: string,
- userAddress: string,
- amountInBaseUnits: BigNumber,
- ): Promise<void> {
- const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
- if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
- this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
- }
- }
- private async _increaseBalanceAsync(
- tokenAddress: string,
- userAddress: string,
- amountInBaseUnits: BigNumber,
- ): Promise<void> {
- const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
- this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
- }
- private async _decreaseBalanceAsync(
- tokenAddress: string,
- userAddress: string,
- amountInBaseUnits: BigNumber,
- ): Promise<void> {
- const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
- this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
- }
-}
diff --git a/packages/0x.js/src/utils/filter_utils.ts b/packages/0x.js/src/utils/filter_utils.ts
deleted file mode 100644
index c5df7321e..000000000
--- a/packages/0x.js/src/utils/filter_utils.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import {
- ConstructorAbi,
- ContractAbi,
- EventAbi,
- FallbackAbi,
- FilterObject,
- LogEntry,
- MethodAbi,
-} from '@0xproject/types';
-import * as ethUtil from 'ethereumjs-util';
-import * as jsSHA3 from 'js-sha3';
-import * as _ from 'lodash';
-import * as uuid from 'uuid/v4';
-
-import { BlockRange, ContractEvents, IndexedFilterValues } from '../types';
-
-const TOPIC_LENGTH = 32;
-
-export const filterUtils = {
- generateUUID(): string {
- return uuid();
- },
- getFilter(
- address: string,
- eventName: ContractEvents,
- indexFilterValues: IndexedFilterValues,
- abi: ContractAbi,
- blockRange?: BlockRange,
- ): FilterObject {
- const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
- const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
- const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
- const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
- const topics = [topicForEventSignature, ...topicsForIndexedArgs];
- let filter: FilterObject = {
- address,
- topics,
- };
- if (!_.isUndefined(blockRange)) {
- filter = {
- ...blockRange,
- ...filter,
- };
- }
- return filter;
- },
- getEventSignatureFromAbiByName(eventAbi: EventAbi, eventName: ContractEvents): string {
- const types = _.map(eventAbi.inputs, 'type');
- const signature = `${eventAbi.name}(${types.join(',')})`;
- return signature;
- },
- getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> {
- const topics: Array<string | null> = [];
- for (const eventInput of abi.inputs) {
- if (!eventInput.indexed) {
- continue;
- }
- if (_.isUndefined(indexFilterValues[eventInput.name])) {
- // Null is a wildcard topic in a JSON-RPC call
- topics.push(null);
- } else {
- const value = indexFilterValues[eventInput.name] as string;
- const buffer = ethUtil.toBuffer(value);
- const paddedBuffer = ethUtil.setLengthLeft(buffer, TOPIC_LENGTH);
- const topic = ethUtil.bufferToHex(paddedBuffer);
- topics.push(topic);
- }
- }
- return topics;
- },
- matchesFilter(log: LogEntry, filter: FilterObject): boolean {
- if (!_.isUndefined(filter.address) && log.address !== filter.address) {
- return false;
- }
- if (!_.isUndefined(filter.topics)) {
- return filterUtils.matchesTopics(log.topics, filter.topics);
- }
- return true;
- },
- matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
- const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
- const matchesTopics = _.every(matchesTopic);
- return matchesTopics;
- },
- matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
- if (_.isArray(filterTopic)) {
- return _.includes(filterTopic, logTopic);
- }
- if (_.isString(filterTopic)) {
- return filterTopic === logTopic;
- }
- // null topic is a wildcard
- return true;
- },
-};
diff --git a/packages/0x.js/src/utils/order_state_utils.ts b/packages/0x.js/src/utils/order_state_utils.ts
deleted file mode 100644
index 38189443b..000000000
--- a/packages/0x.js/src/utils/order_state_utils.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { ZeroEx } from '../0x';
-import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
-import { RemainingFillableCalculator } from '../order_watcher/remaining_fillable_calculator';
-import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
-import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
-import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types';
-
-const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
-
-export class OrderStateUtils {
- private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
- private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
- private static _validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
- const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
- orderRelevantState.filledTakerTokenAmount,
- );
- const availableTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
- if (availableTakerTokenAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
- }
-
- if (orderRelevantState.makerBalance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerBalance);
- }
- if (orderRelevantState.makerProxyAllowance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerAllowance);
- }
- if (!signedOrder.makerFee.eq(0)) {
- if (orderRelevantState.makerFeeBalance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerFeeBalance);
- }
- if (orderRelevantState.makerFeeProxyAllowance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerFeeAllowance);
- }
- }
- const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
- .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
- .dividedBy(signedOrder.makerTokenAmount);
- if (
- orderRelevantState.remainingFillableTakerTokenAmount.lessThan(
- minFillableTakerTokenAmountWithinNoRoundingErrorRange,
- )
- ) {
- throw new Error(ExchangeContractErrs.OrderFillRoundingError);
- }
- }
- constructor(
- balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
- orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore,
- ) {
- this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
- this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
- }
- public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
- const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- try {
- OrderStateUtils._validateIfOrderIsValid(signedOrder, orderRelevantState);
- const orderState: OrderStateValid = {
- isValid: true,
- orderHash,
- orderRelevantState,
- };
- return orderState;
- } catch (err) {
- const orderState: OrderStateInvalid = {
- isValid: false,
- orderHash,
- error: err.message,
- };
- return orderState;
- }
- }
- public async getOrderRelevantStateAsync(signedOrder: SignedOrder): Promise<OrderRelevantState> {
- // HACK: We access the private property here but otherwise the interface will be less nice.
- // If we pass it from the instantiator - there is no opportunity to get it there
- // because JS doesn't support async constructors.
- // Moreover - it's cached under the hood so it's equivalent to an async constructor.
- const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
- const zrxTokenAddress = exchange.getZRXTokenAddress();
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- const makerBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
- );
- const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
- );
- const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
- zrxTokenAddress,
- signedOrder.maker,
- );
- const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
- zrxTokenAddress,
- signedOrder.maker,
- );
- const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
- const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
- orderHash,
- );
- const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash);
- const totalMakerTokenAmount = signedOrder.makerTokenAmount;
- const totalTakerTokenAmount = signedOrder.takerTokenAmount;
- const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount);
- const remainingMakerTokenAmount = remainingTakerTokenAmount
- .times(totalMakerTokenAmount)
- .dividedToIntegerBy(totalTakerTokenAmount);
- const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]);
- const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]);
-
- const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress;
- const remainingFillableCalculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- const remainingFillableMakerTokenAmount = remainingFillableCalculator.computeRemainingMakerFillable();
- const remainingFillableTakerTokenAmount = remainingFillableCalculator.computeRemainingTakerFillable();
- const orderRelevantState = {
- makerBalance,
- makerProxyAllowance,
- makerFeeBalance,
- makerFeeProxyAllowance,
- filledTakerTokenAmount,
- cancelledTakerTokenAmount,
- remainingFillableMakerTokenAmount,
- remainingFillableTakerTokenAmount,
- };
- return orderRelevantState;
- }
-}
diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts
deleted file mode 100644
index f32bf43d0..000000000
--- a/packages/0x.js/src/utils/order_validation_utils.ts
+++ /dev/null
@@ -1,217 +0,0 @@
-import { Order, SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { ZeroEx } from '../0x';
-import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
-import { ExchangeContractErrs, TradeSide, TransferType, ZeroExError } from '../types';
-import { constants } from '../utils/constants';
-import { utils } from '../utils/utils';
-
-import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
-
-export class OrderValidationUtils {
- private _exchangeWrapper: ExchangeWrapper;
- public static validateCancelOrderThrowIfInvalid(
- order: Order,
- cancelTakerTokenAmount: BigNumber,
- unavailableTakerTokenAmount: BigNumber,
- ): void {
- if (cancelTakerTokenAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
- }
- if (order.takerTokenAmount.eq(unavailableTakerTokenAmount)) {
- throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
- }
- const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
- if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
- throw new Error(ExchangeContractErrs.OrderCancelExpired);
- }
- }
- public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTradeEmulator: ExchangeTransferSimulator,
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- senderAddress: string,
- zrxTokenAddress: string,
- ): Promise<void> {
- const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerTokenAmount,
- );
- await exchangeTradeEmulator.transferFromAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
- senderAddress,
- fillMakerTokenAmount,
- TradeSide.Maker,
- TransferType.Trade,
- );
- await exchangeTradeEmulator.transferFromAsync(
- signedOrder.takerTokenAddress,
- senderAddress,
- signedOrder.maker,
- fillTakerTokenAmount,
- TradeSide.Taker,
- TransferType.Trade,
- );
- const makerFeeAmount = OrderValidationUtils._getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- );
- await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress,
- signedOrder.maker,
- signedOrder.feeRecipient,
- makerFeeAmount,
- TradeSide.Maker,
- TransferType.Fee,
- );
- const takerFeeAmount = OrderValidationUtils._getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.takerFee,
- );
- await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress,
- senderAddress,
- signedOrder.feeRecipient,
- takerFeeAmount,
- TradeSide.Taker,
- TransferType.Fee,
- );
- }
- private static _validateRemainingFillAmountNotZeroOrThrow(
- takerTokenAmount: BigNumber,
- unavailableTakerTokenAmount: BigNumber,
- ) {
- if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
- throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
- }
- }
- private static _validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
- const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
- if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
- throw new Error(ExchangeContractErrs.OrderFillExpired);
- }
- }
- private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
- const fillMakerTokenAmount = numerator
- .mul(target)
- .div(denominator)
- .round(0);
- return fillMakerTokenAmount;
- }
- constructor(exchangeWrapper: ExchangeWrapper) {
- this._exchangeWrapper = exchangeWrapper;
- }
- public async validateOrderFillableOrThrowAsync(
- exchangeTradeEmulator: ExchangeTransferSimulator,
- signedOrder: SignedOrder,
- zrxTokenAddress: string,
- expectedFillTakerTokenAmount?: BigNumber,
- ): Promise<void> {
- const orderHash = utils.getOrderHashHex(signedOrder);
- const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
- OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
- signedOrder.takerTokenAmount,
- unavailableTakerTokenAmount,
- );
- OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
- let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
- if (!_.isUndefined(expectedFillTakerTokenAmount)) {
- fillTakerTokenAmount = expectedFillTakerTokenAmount;
- }
- const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerTokenAmount,
- );
- await exchangeTradeEmulator.transferFromAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
- signedOrder.taker,
- fillMakerTokenAmount,
- TradeSide.Maker,
- TransferType.Trade,
- );
- const makerFeeAmount = OrderValidationUtils._getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- );
- await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress,
- signedOrder.maker,
- signedOrder.feeRecipient,
- makerFeeAmount,
- TradeSide.Maker,
- TransferType.Fee,
- );
- }
- public async validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator: ExchangeTransferSimulator,
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string,
- zrxTokenAddress: string,
- ): Promise<BigNumber> {
- if (fillTakerTokenAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderFillAmountZero);
- }
- const orderHash = utils.getOrderHashHex(signedOrder);
- if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
- throw new Error(ZeroExError.InvalidSignature);
- }
- const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
- OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
- signedOrder.takerTokenAmount,
- unavailableTakerTokenAmount,
- );
- if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
- throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
- }
- OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
- const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
- const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount)
- ? remainingTakerTokenAmount
- : fillTakerTokenAmount;
- await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- filledTakerTokenAmount,
- takerAddress,
- zrxTokenAddress,
- );
-
- const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
- filledTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerTokenAmount,
- );
- if (wouldRoundingErrorOccur) {
- throw new Error(ExchangeContractErrs.OrderFillRoundingError);
- }
- return filledTakerTokenAmount;
- }
- public async validateFillOrKillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator: ExchangeTransferSimulator,
- signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string,
- zrxTokenAddress: string,
- ): Promise<void> {
- const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
- exchangeTradeEmulator,
- signedOrder,
- fillTakerTokenAmount,
- takerAddress,
- zrxTokenAddress,
- );
- if (filledTakerTokenAmount !== fillTakerTokenAmount) {
- throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
- }
- }
-}
diff --git a/packages/0x.js/src/utils/signature_utils.ts b/packages/0x.js/src/utils/signature_utils.ts
deleted file mode 100644
index 46f167339..000000000
--- a/packages/0x.js/src/utils/signature_utils.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { ECSignature } from '@0xproject/types';
-import * as ethUtil from 'ethereumjs-util';
-
-export const signatureUtils = {
- isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
- const dataBuff = ethUtil.toBuffer(data);
- const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
- try {
- const pubKey = ethUtil.ecrecover(
- msgHashBuff,
- signature.v,
- ethUtil.toBuffer(signature.r),
- ethUtil.toBuffer(signature.s),
- );
- const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
- return retrievedAddress === signerAddress;
- } catch (err) {
- return false;
- }
- },
- parseSignatureHexAsVRS(signatureHex: string): ECSignature {
- const signatureBuffer = ethUtil.toBuffer(signatureHex);
- let v = signatureBuffer[0];
- if (v < 27) {
- v += 27;
- }
- const r = signatureBuffer.slice(1, 33);
- const s = signatureBuffer.slice(33, 65);
- const ecSignature: ECSignature = {
- v,
- r: ethUtil.bufferToHex(r),
- s: ethUtil.bufferToHex(s),
- };
- return ecSignature;
- },
- parseSignatureHexAsRSV(signatureHex: string): ECSignature {
- const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
- const ecSignature: ECSignature = {
- v,
- r: ethUtil.bufferToHex(r),
- s: ethUtil.bufferToHex(s),
- };
- return ecSignature;
- },
-};
diff --git a/packages/0x.js/src/utils/utils.ts b/packages/0x.js/src/utils/utils.ts
deleted file mode 100644
index c8bcd907e..000000000
--- a/packages/0x.js/src/utils/utils.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import BN = require('bn.js');
-import * as ethABI from 'ethereumjs-abi';
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
-
-export const utils = {
- /**
- * Converts BigNumber instance to BN
- * The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that
- * expects values of Solidity type `uint` to be passed as type `BN`.
- * We do not use BN anywhere else in the codebase.
- */
- bigNumberToBN(value: BigNumber) {
- return new BN(value.toString(), 10);
- },
- spawnSwitchErr(name: string, value: any): Error {
- return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
- },
- getOrderHashHex(order: Order | SignedOrder): string {
- const orderParts = [
- { value: order.exchangeContractAddress, type: SolidityTypes.Address },
- { value: order.maker, type: SolidityTypes.Address },
- { value: order.taker, type: SolidityTypes.Address },
- { value: order.makerTokenAddress, type: SolidityTypes.Address },
- { value: order.takerTokenAddress, type: SolidityTypes.Address },
- { value: order.feeRecipient, type: SolidityTypes.Address },
- {
- value: utils.bigNumberToBN(order.makerTokenAmount),
- type: SolidityTypes.Uint256,
- },
- {
- value: utils.bigNumberToBN(order.takerTokenAmount),
- type: SolidityTypes.Uint256,
- },
- {
- value: utils.bigNumberToBN(order.makerFee),
- type: SolidityTypes.Uint256,
- },
- {
- value: utils.bigNumberToBN(order.takerFee),
- type: SolidityTypes.Uint256,
- },
- {
- value: utils.bigNumberToBN(order.expirationUnixTimestampSec),
- type: SolidityTypes.Uint256,
- },
- { value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
- ];
- const types = _.map(orderParts, o => o.type);
- const values = _.map(orderParts, o => o.value);
- const hashBuff = ethABI.soliditySHA3(types, values);
- const hashHex = ethUtil.bufferToHex(hashBuff);
- return hashHex;
- },
- getCurrentUnixTimestampSec(): BigNumber {
- return new BigNumber(Date.now() / 1000).round();
- },
- getCurrentUnixTimestampMs(): BigNumber {
- return new BigNumber(Date.now());
- },
-};
diff --git a/packages/0x.js/test/0x.js_test.ts b/packages/0x.js/test/0x.js_test.ts
index 70e85aa52..be2a94482 100644
--- a/packages/0x.js/test/0x.js_test.ts
+++ b/packages/0x.js/test/0x.js_test.ts
@@ -1,120 +1,78 @@
-import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
+import { ContractWrappers } from '@0xproject/contract-wrappers';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
-import * as _ from 'lodash';
import 'mocha';
-import * as Sinon from 'sinon';
-import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src';
+import { ERC20TokenApprovalEventArgs, ERC20TokenEvents, LogWithDecodedArgs, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
+import { tokenUtils } from './utils/token_utils';
+import { provider, web3Wrapper } from './utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
chaiSetup.configure();
const expect = chai.expect;
-const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
-
describe('ZeroEx library', () => {
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- const zeroEx = new ZeroEx(web3.currentProvider, config);
+ let zeroEx: ZeroEx;
+ before(async () => {
+ const config = {
+ networkId: constants.TESTRPC_NETWORK_ID,
+ };
+ zeroEx = new ZeroEx(provider, config);
+ });
describe('#setProvider', () => {
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
// Instantiate the contract instances with the current provider
await (zeroEx.exchange as any)._getExchangeContractAsync();
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
- expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
- const newProvider = web3Factory.getRpcProvider();
// Add property to newProvider so that we can differentiate it from old provider
- (newProvider as any).zeroExTestId = 1;
- zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
+ (provider as any).zeroExTestId = 1;
+ zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
- expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
- // Check that all nested web3 wrapper instances return the updated provider
- const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getProvider();
- expect(nestedWeb3WrapperProvider.zeroExTestId).to.be.a('number');
+ // Check that all nested zeroExContract/web3Wrapper instances return the updated provider
+ const nestedWeb3WrapperProvider = ((zeroEx as any)._contractWrappers as ContractWrappers).getProvider();
+ expect((nestedWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getProvider();
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
- const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getProvider();
- expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
});
});
describe('#isValidSignature', () => {
- // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
- // the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
- const signature = {
- v: 27,
- r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
- s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
- };
+ const ethSignSignature =
+ '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
+ const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
it("should return false if the data doesn't pertain to the signature & address", async () => {
- expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
+ (zeroEx.exchange as any).isValidSignatureAsync(bytes32Zeros, address, ethSignSignature),
).to.become(false);
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
- expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
- dataHex,
- signature,
- validUnrelatedAddress,
- ),
+ (zeroEx.exchange as any).isValidSignatureAsync(dataHex, validUnrelatedAddress, ethSignSignature),
).to.become(false);
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
- const wrongSignature = _.assign({}, signature, { v: 28 });
- expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
- return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
- ).to.become(false);
+ const signatureArray = ethSignSignature.split('');
+ // tslint:disable-next-line:custom-no-magic-numbers
+ signatureArray[5] = 'C'; // V = 28, instead of 27
+ const wrongSignature = signatureArray.join('');
+ return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, wrongSignature)).to.become(
+ false,
+ );
});
it('should return true if the signature does pertain to the dataHex & address', async () => {
- const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
- expect(isValidSignatureLocal).to.be.true();
- return expect(
- (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
- ).to.become(true);
- });
- });
- describe('#generateSalt', () => {
- it('generates different salts', () => {
- const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt());
- expect(equal).to.be.false();
- });
- it('generates salt in range [0..2^256)', () => {
- const salt = ZeroEx.generatePseudoRandomSalt();
- expect(salt.greaterThanOrEqualTo(0)).to.be.true();
- const twoPow256 = new BigNumber(2).pow(256);
- expect(salt.lessThan(twoPow256)).to.be.true();
- });
- });
- describe('#isValidOrderHash', () => {
- it('returns false if the value is not a hex string', () => {
- const isValid = ZeroEx.isValidOrderHash('not a hex');
- expect(isValid).to.be.false();
- });
- it('returns false if the length is wrong', () => {
- const isValid = ZeroEx.isValidOrderHash('0xdeadbeef');
- expect(isValid).to.be.false();
- });
- it('returns true if order hash is correct', () => {
- const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0'));
- expect(isValid).to.be.true();
+ return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, ethSignSignature)).to.become(
+ true,
+ );
});
});
describe('#toUnitAmount', () => {
@@ -149,106 +107,6 @@ describe('ZeroEx library', () => {
);
});
});
- describe('#getOrderHashHex', () => {
- const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
- const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
- const order: Order = {
- maker: constants.NULL_ADDRESS,
- taker: constants.NULL_ADDRESS,
- feeRecipient: constants.NULL_ADDRESS,
- makerTokenAddress: constants.NULL_ADDRESS,
- takerTokenAddress: constants.NULL_ADDRESS,
- exchangeContractAddress: fakeExchangeContractAddress,
- salt: new BigNumber(0),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- makerTokenAmount: new BigNumber(0),
- takerTokenAmount: new BigNumber(0),
- expirationUnixTimestampSec: new BigNumber(0),
- };
- it('calculates the order hash', async () => {
- const orderHash = ZeroEx.getOrderHashHex(order);
- expect(orderHash).to.be.equal(expectedOrderHash);
- });
- it('throws a readable error message if taker format is invalid', async () => {
- const orderWithInvalidtakerFormat = {
- ...order,
- taker: (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 ZeroEx.NULL_ADDRESS';
- expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
- });
- });
- describe('#signOrderHashAsync', () => {
- let stubs: Sinon.SinonStub[] = [];
- let makerAddress: string;
- before(async () => {
- const availableAddreses = await zeroEx.getAvailableAddressesAsync();
- makerAddress = availableAddreses[0];
- });
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should return the correct ECSignature', async () => {
- const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
- const expectedECSignature = {
- v: 27,
- r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
- s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
- };
- const ecSignature = await zeroEx.signOrderHashAsync(
- orderHash,
- makerAddress,
- SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
- );
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
- const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- const signature =
- '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
- const expectedECSignature = {
- v: 27,
- r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
- s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
- };
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
- Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
- ];
-
- const ecSignature = await zeroEx.signOrderHashAsync(
- orderHash,
- makerAddress,
- SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
- );
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
- const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
- const signature =
- '0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
- const expectedECSignature = {
- v: 27,
- r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
- s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
- };
- stubs = [
- Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
- Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
- ];
-
- const ecSignature = await zeroEx.signOrderHashAsync(
- orderHash,
- makerAddress,
- SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
- );
- expect(ecSignature).to.deep.equal(expectedECSignature);
- });
- });
describe('#awaitTransactionMinedAsync', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -259,17 +117,16 @@ describe('ZeroEx library', () => {
it('returns transaction receipt with decoded logs', async () => {
const availableAddresses = await zeroEx.getAvailableAddressesAsync();
const coinbase = availableAddresses[0];
- const tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const tokenUtils = new TokenUtils(tokens);
- const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- const proxyAddress = zeroEx.proxy.getContractAddress();
- const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
+ const zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
+ const erc20ProxyAddress = zeroEx.erc20Proxy.getContractAddress();
+ const txHash = await zeroEx.erc20Token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
- const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
- expect(log.event).to.be.equal(TokenEvents.Approval);
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ERC20TokenApprovalEventArgs>;
+ expect(log.event).to.be.equal(ERC20TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);
- expect(log.args._spender).to.be.equal(proxyAddress);
- expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ expect(log.args._spender).to.be.equal(erc20ProxyAddress);
+ expect(log.args._value).to.be.bignumber.equal(zeroEx.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
});
describe('#config', () => {
@@ -278,18 +135,16 @@ describe('ZeroEx library', () => {
exchangeContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
- const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
+ const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
- it('allows to specify token registry token contract address', async () => {
+ it('allows to specify erc20Proxy contract address', async () => {
const zeroExConfig = {
- tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
+ erc20ProxyContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
- const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
- expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
- ZeroEx.NULL_ADDRESS,
- );
+ const zeroExWithWrongERC20ProxyAddress = new ZeroEx(provider, zeroExConfig);
+ expect(zeroExWithWrongERC20ProxyAddress.erc20Proxy.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
});
});
diff --git a/packages/0x.js/test/artifacts_test.ts b/packages/0x.js/test/artifacts_test.ts
deleted file mode 100644
index e8ab9aa97..000000000
--- a/packages/0x.js/test/artifacts_test.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import * as fs from 'fs';
-import HDWalletProvider = require('truffle-hdwallet-provider');
-
-import { ZeroEx } from '../src';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-
-chaiSetup.configure();
-
-// Those tests are slower cause they're talking to a remote node
-const TIMEOUT = 10000;
-
-describe('Artifacts', () => {
- describe('contracts are deployed on kovan', () => {
- const kovanRpcUrl = constants.KOVAN_RPC_URL;
- const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
- const packageJSON = JSON.parse(packageJSONContent);
- const mnemonic = packageJSON.config.mnemonic;
- const web3Provider = new HDWalletProvider(mnemonic, kovanRpcUrl);
- const config = {
- networkId: constants.KOVAN_NETWORK_ID,
- };
- const zeroEx = new ZeroEx(web3Provider, config);
- it('token registry contract is deployed', async () => {
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
- }).timeout(TIMEOUT);
- it('proxy contract is deployed', async () => {
- await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
- }).timeout(TIMEOUT);
- it('exchange contract is deployed', async () => {
- await (zeroEx.exchange as any)._getExchangeContractAsync();
- }).timeout(TIMEOUT);
- });
- describe('contracts are deployed on ropsten', () => {
- const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
- const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
- const packageJSON = JSON.parse(packageJSONContent);
- const mnemonic = packageJSON.config.mnemonic;
- const web3Provider = new HDWalletProvider(mnemonic, ropstenRpcUrl);
- const config = {
- networkId: constants.ROPSTEN_NETWORK_ID,
- };
- const zeroEx = new ZeroEx(web3Provider, config);
- it('token registry contract is deployed', async () => {
- await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
- }).timeout(TIMEOUT);
- it('proxy contract is deployed', async () => {
- await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
- }).timeout(TIMEOUT);
- it('exchange contract is deployed', async () => {
- await (zeroEx.exchange as any)._getExchangeContractAsync();
- }).timeout(TIMEOUT);
- });
-});
diff --git a/packages/0x.js/test/assert_test.ts b/packages/0x.js/test/assert_test.ts
deleted file mode 100644
index c4451742f..000000000
--- a/packages/0x.js/test/assert_test.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { web3Factory } from '@0xproject/dev-utils';
-import * as chai from 'chai';
-import 'mocha';
-
-import { ZeroEx } from '../src';
-import { assert } from '../src/utils/assert';
-
-import { constants } from './utils/constants';
-
-const expect = chai.expect;
-
-describe('Assertion library', () => {
- const web3 = web3Factory.create();
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- const zeroEx = new ZeroEx(web3.currentProvider, config);
- describe('#isSenderAddressHexAsync', () => {
- it('throws when address is invalid', async () => {
- const address = '0xdeadbeef';
- const varName = 'address';
- return expect(
- assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper),
- ).to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
- });
- it('throws when address is unavailable', async () => {
- const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
- const varName = 'address';
- return expect(
- assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper),
- ).to.be.rejectedWith(
- `Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
- );
- });
- it("doesn't throw if address is available", async () => {
- const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
- const varName = 'address';
- return expect(
- assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper),
- ).to.become(undefined);
- });
- });
-});
diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts
deleted file mode 100644
index 6237ccf23..000000000
--- a/packages/0x.js/test/ether_token_wrapper_test.ts
+++ /dev/null
@@ -1,387 +0,0 @@
-import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import 'mocha';
-import * as Web3 from 'web3';
-
-import {
- ApprovalContractEventArgs,
- BlockParamLiteral,
- BlockRange,
- DecodedLogEvent,
- DepositContractEventArgs,
- EtherTokenEvents,
- Token,
- TransferContractEventArgs,
- WithdrawalContractEventArgs,
- ZeroEx,
- ZeroExError,
-} from '../src';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { reportNodeCallbackErrors } from './utils/report_callback_errors';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
-// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
-// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount
-// required to pay gas costs.
-const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
-
-describe('EtherTokenWrapper', () => {
- let zeroEx: ZeroEx;
- let tokens: Token[];
- let userAddresses: string[];
- let addressWithETH: string;
- let wethContractAddress: string;
- let depositWeiAmount: BigNumber;
- let decimalPlaces: number;
- let addressWithoutFunds: string;
- const gasPrice = new BigNumber(1);
- const zeroExConfig = {
- gasPrice,
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- const transferAmount = new BigNumber(42);
- const allowanceAmount = new BigNumber(42);
- const depositAmount = new BigNumber(42);
- const withdrawalAmount = new BigNumber(42);
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- addressWithETH = userAddresses[0];
- wethContractAddress = zeroEx.etherToken.getContractAddressIfExists() as string;
- depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5));
- decimalPlaces = 7;
- addressWithoutFunds = userAddresses[1];
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#getContractAddressIfExists', async () => {
- it('should return contract address if connected to a known network', () => {
- const contractAddressIfExists = zeroEx.etherToken.getContractAddressIfExists();
- expect(contractAddressIfExists).to.not.be.undefined();
- });
- it('should throw if connected to a private network and contract addresses are not specified', () => {
- const UNKNOWN_NETWORK_NETWORK_ID = 10;
- expect(
- () =>
- new ZeroEx(web3.currentProvider, {
- networkId: UNKNOWN_NETWORK_NETWORK_ID,
- } as any),
- ).to.throw();
- });
- });
- describe('#depositAsync', () => {
- it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- expect(preETHBalance).to.be.bignumber.gt(0);
- expect(preWETHBalance).to.be.bignumber.equal(0);
-
- const txHash = await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
-
- expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount);
- const remainingETHInWei = preETHBalance.minus(depositWeiAmount);
- const gasCost = remainingETHInWei.minus(postETHBalanceInWei);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- });
- it('should throw if user has insufficient ETH balance for deposit', async () => {
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
-
- const extraETHBalance = (zeroEx as any)._web3Wrapper.toWei(5, 'ether');
- const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
-
- return expect(
- zeroEx.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH),
- ).to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
- });
- });
- describe('#withdrawAsync', () => {
- it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => {
- const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
-
- await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
-
- const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
- const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- let gasCost = expectedPreETHBalance.minus(preETHBalance);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
-
- const txHash = await zeroEx.etherToken.withdrawAsync(wethContractAddress, depositWeiAmount, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
- const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
-
- expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0);
- const expectedETHBalance = preETHBalance.add(depositWeiAmount).round(decimalPlaces);
- gasCost = expectedETHBalance.minus(postETHBalance);
- expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
- });
- it('should throw if user has insufficient WETH balance for withdrawal', async () => {
- const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
- expect(preWETHBalance).to.be.bignumber.equal(0);
-
- const overWETHBalance = preWETHBalance.add(999999999);
-
- return expect(
- zeroEx.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH),
- ).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
- });
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- let etherTokenAddress: string;
- before(() => {
- const tokenUtils = new TokenUtils(tokens);
- const etherToken = tokenUtils.getWethTokenOrThrow();
- etherTokenAddress = etherToken.address;
- });
- afterEach(() => {
- zeroEx.etherToken.unsubscribeAll();
- });
- // Hack: Mocha does not allow a test to be both async and have a `done` callback
- // Since we need to await the receipt of the event in the `subscribe` callback,
- // we do need both. A hack is to make the top-level async fn w/ a done callback and then
- // wrap the rest of the test in an async block
- // Source: https://github.com/mochajs/mocha/issues/2407
- it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- expect(logEvent.isRemoved).to.be.false();
- expect(logEvent.log.logIndex).to.be.equal(0);
- expect(logEvent.log.transactionIndex).to.be.equal(0);
- expect(logEvent.log.blockNumber).to.be.a('number');
- const args = logEvent.log.args;
- expect(args._from).to.be.equal(addressWithETH);
- expect(args._to).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(transferAmount);
- },
- );
- await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
- zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
- await zeroEx.token.transferAsync(
- etherTokenAddress,
- addressWithETH,
- addressWithoutFunds,
- transferAmount,
- );
- })().catch(done);
- });
- it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- expect(logEvent.isRemoved).to.be.false();
- const args = logEvent.log.args;
- expect(args._owner).to.be.equal(addressWithETH);
- expect(args._spender).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(allowanceAmount);
- },
- );
- zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(
- etherTokenAddress,
- addressWithETH,
- addressWithoutFunds,
- allowanceAmount,
- );
- })().catch(done);
- });
- it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- expect(logEvent.isRemoved).to.be.false();
- const args = logEvent.log.args;
- expect(args._owner).to.be.equal(addressWithETH);
- expect(args._value).to.be.bignumber.equal(depositAmount);
- },
- );
- zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
- await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
- })().catch(done);
- });
- it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- expect(logEvent.isRemoved).to.be.false();
- const args = logEvent.log.args;
- expect(args._owner).to.be.equal(addressWithETH);
- expect(args._value).to.be.bignumber.equal(depositAmount);
- },
- );
- await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
- zeroEx.etherToken.subscribe(
- etherTokenAddress,
- EtherTokenEvents.Withdrawal,
- indexFilterValues,
- callback,
- );
- await zeroEx.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH);
- })().catch(done);
- });
- it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- zeroEx.etherToken.subscribe(
- etherTokenAddress,
- EtherTokenEvents.Transfer,
- indexFilterValues,
- callbackNeverToBeCalled,
- );
- const callbackToBeCalled = reportNodeCallbackErrors(done)();
- const newProvider = web3Factory.getRpcProvider();
- zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
- await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
- zeroEx.etherToken.subscribe(
- etherTokenAddress,
- EtherTokenEvents.Transfer,
- indexFilterValues,
- callbackToBeCalled,
- );
- await zeroEx.token.transferAsync(
- etherTokenAddress,
- addressWithETH,
- addressWithoutFunds,
- transferAmount,
- );
- })().catch(done);
- });
- it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
- const subscriptionToken = zeroEx.etherToken.subscribe(
- etherTokenAddress,
- EtherTokenEvents.Transfer,
- indexFilterValues,
- callbackNeverToBeCalled,
- );
- zeroEx.etherToken.unsubscribe(subscriptionToken);
- await zeroEx.token.transferAsync(
- etherTokenAddress,
- addressWithETH,
- addressWithoutFunds,
- transferAmount,
- );
- done();
- })().catch(done);
- });
- });
- describe('#getLogsAsync', () => {
- let etherTokenAddress: string;
- let tokenTransferProxyAddress: string;
- const blockRange: BlockRange = {
- fromBlock: 0,
- toBlock: BlockParamLiteral.Latest,
- };
- let txHash: string;
- before(() => {
- addressWithETH = userAddresses[0];
- const tokenUtils = new TokenUtils(tokens);
- const etherToken = tokenUtils.getWethTokenOrThrow();
- etherTokenAddress = etherToken.address;
- tokenTransferProxyAddress = zeroEx.proxy.getContractAddress();
- });
- it('should get logs with decoded args emitted by Approval', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = EtherTokenEvents.Approval;
- const indexFilterValues = {};
- const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
- etherTokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(logs[0].event).to.be.equal(eventName);
- expect(args._owner).to.be.equal(addressWithETH);
- expect(args._spender).to.be.equal(tokenTransferProxyAddress);
- expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- it('should get logs with decoded args emitted by Deposit', async () => {
- await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
- const eventName = EtherTokenEvents.Deposit;
- const indexFilterValues = {};
- const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
- etherTokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(logs[0].event).to.be.equal(eventName);
- expect(args._owner).to.be.equal(addressWithETH);
- expect(args._value).to.be.bignumber.equal(depositAmount);
- });
- it('should only get the logs with the correct event name', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const differentEventName = EtherTokenEvents.Transfer;
- const indexFilterValues = {};
- const logs = await zeroEx.etherToken.getLogsAsync(
- etherTokenAddress,
- differentEventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(0);
- });
- it('should only get the logs with the correct indexed fields', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithoutFunds);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = EtherTokenEvents.Approval;
- const indexFilterValues = {
- _owner: addressWithETH,
- };
- const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
- etherTokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(args._owner).to.be.equal(addressWithETH);
- });
- });
-});
diff --git a/packages/0x.js/test/event_watcher_test.ts b/packages/0x.js/test/event_watcher_test.ts
deleted file mode 100644
index 2fa6c0580..000000000
--- a/packages/0x.js/test/event_watcher_test.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import { web3Factory } from '@0xproject/dev-utils';
-import { LogEntry } from '@0xproject/types';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-import * as Sinon from 'sinon';
-import * as Web3 from 'web3';
-
-import { LogEvent } from '../src';
-import { EventWatcher } from '../src/order_watcher/event_watcher';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { reportNodeCallbackErrors } from './utils/report_callback_errors';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('EventWatcher', () => {
- let web3: Web3;
- let stubs: Sinon.SinonStub[] = [];
- let eventWatcher: EventWatcher;
- let web3Wrapper: Web3Wrapper;
- const logA: LogEntry = {
- address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: [],
- transactionHash: '0x004881d38cd4a8f72f1a0d68c8b9b8124504706041ff37019c1d1ed6bfda8e17',
- transactionIndex: 0,
- };
- const logB: LogEntry = {
- address: '0x8d12a197cb00d4747a1fe03395095ce2a5cc6819',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
- transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
- transactionIndex: 0,
- };
- const logC: LogEntry = {
- address: '0x1d271f8b174adef58f1587ce68f8f27271ac4ca5',
- blockHash: null,
- blockNumber: null,
- data: '',
- logIndex: null,
- topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
- transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
- transactionIndex: 0,
- };
- before(async () => {
- web3 = web3Factory.create();
- const pollingIntervalMs = 10;
- web3Wrapper = new Web3Wrapper(web3.currentProvider);
- eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
- });
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- eventWatcher.unsubscribe();
- });
- it('correctly emits initial log events', (done: DoneCallback) => {
- const logs: LogEntry[] = [logA, logB];
- const expectedLogEvents = [
- {
- removed: false,
- ...logA,
- },
- {
- removed: false,
- ...logB,
- },
- ];
- const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
- getLogsStub.onCall(0).returns(logs);
- stubs.push(getLogsStub);
- const expectedToBeCalledOnce = false;
- const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
- const expectedLogEvent = expectedLogEvents.shift();
- expect(event).to.be.deep.equal(expectedLogEvent);
- if (_.isEmpty(expectedLogEvents)) {
- done();
- }
- });
- eventWatcher.subscribe(callback);
- });
- it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
- const initialLogs: LogEntry[] = [logA, logB];
- const changedLogs: LogEntry[] = [logA, logC];
- const expectedLogEvents = [
- {
- removed: false,
- ...logA,
- },
- {
- removed: false,
- ...logB,
- },
- {
- removed: true,
- ...logB,
- },
- {
- removed: false,
- ...logC,
- },
- ];
- const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
- getLogsStub.onCall(0).returns(initialLogs);
- getLogsStub.onCall(1).returns(changedLogs);
- stubs.push(getLogsStub);
- const expectedToBeCalledOnce = false;
- const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
- const expectedLogEvent = expectedLogEvents.shift();
- expect(event).to.be.deep.equal(expectedLogEvent);
- if (_.isEmpty(expectedLogEvents)) {
- done();
- }
- });
- eventWatcher.subscribe(callback);
- });
-});
diff --git a/packages/0x.js/test/exchange_transfer_simulator_test.ts b/packages/0x.js/test/exchange_transfer_simulator_test.ts
deleted file mode 100644
index 4447a61cb..000000000
--- a/packages/0x.js/test/exchange_transfer_simulator_test.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-
-import { ExchangeContractErrs, Token, ZeroEx } from '../src';
-import { TradeSide, TransferType } from '../src/types';
-import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('ExchangeTransferSimulator', () => {
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- const zeroEx = new ZeroEx(web3.currentProvider, config);
- const transferAmount = new BigNumber(5);
- let userAddresses: string[];
- let tokens: Token[];
- let coinbase: string;
- let sender: string;
- let recipient: string;
- let exampleTokenAddress: string;
- let exchangeTransferSimulator: ExchangeTransferSimulator;
- let txHash: string;
- before(async () => {
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [coinbase, sender, recipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- exampleTokenAddress = tokens[0].address;
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#transferFromAsync', () => {
- beforeEach(() => {
- exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
- });
- it("throws if the user doesn't have enough allowance", async () => {
- return expect(
- exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress,
- sender,
- recipient,
- transferAmount,
- TradeSide.Taker,
- TransferType.Trade,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
- });
- it("throws if the user doesn't have enough balance", async () => {
- txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- return expect(
- exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress,
- sender,
- recipient,
- transferAmount,
- TradeSide.Maker,
- TransferType.Trade,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
- });
- it('updates balances and proxyAllowance after transfer', async () => {
- txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- await exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress,
- sender,
- recipient,
- transferAmount,
- TradeSide.Taker,
- TransferType.Trade,
- );
- const store = (exchangeTransferSimulator as any)._store;
- const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
- const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
- const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
- expect(senderBalance).to.be.bignumber.equal(0);
- expect(recipientBalance).to.be.bignumber.equal(transferAmount);
- expect(senderProxyAllowance).to.be.bignumber.equal(0);
- });
- it("doesn't update proxyAllowance after transfer if unlimited", async () => {
- txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- await exchangeTransferSimulator.transferFromAsync(
- exampleTokenAddress,
- sender,
- recipient,
- transferAmount,
- TradeSide.Taker,
- TransferType.Trade,
- );
- const store = (exchangeTransferSimulator as any)._store;
- const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
- const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
- const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
- expect(senderBalance).to.be.bignumber.equal(0);
- expect(recipientBalance).to.be.bignumber.equal(transferAmount);
- expect(senderProxyAllowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- });
-});
diff --git a/packages/0x.js/test/exchange_wrapper_test.ts b/packages/0x.js/test/exchange_wrapper_test.ts
deleted file mode 100644
index cfc390bae..000000000
--- a/packages/0x.js/test/exchange_wrapper_test.ts
+++ /dev/null
@@ -1,1159 +0,0 @@
-import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-import * as Web3 from 'web3';
-
-import {
- BlockRange,
- DecodedLogEvent,
- ExchangeContractErrs,
- ExchangeEvents,
- LogCancelContractEventArgs,
- LogFillContractEventArgs,
- OrderCancellationRequest,
- OrderFillRequest,
- SignedOrder,
- Token,
- ZeroEx,
-} from '../src';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { FillScenarios } from './utils/fill_scenarios';
-import { reportNodeCallbackErrors } from './utils/report_callback_errors';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777';
-
-describe('ExchangeWrapper', () => {
- let zeroEx: ZeroEx;
- let tokenUtils: TokenUtils;
- let tokens: Token[];
- let userAddresses: string[];
- let zrxTokenAddress: string;
- let fillScenarios: FillScenarios;
- let exchangeContractAddress: string;
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- exchangeContractAddress = zeroEx.exchange.getContractAddress();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- await fillScenarios.initTokenBalancesAsync();
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('fillOrKill order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const takerTokenFillAmount = new BigNumber(5);
- before(async () => {
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- describe('#batchFillOrKillAsync', () => {
- it('successfully batch fillOrKill', async () => {
- const fillableAmount = new BigNumber(5);
- const partialFillTakerAmount = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const orderFillRequests = [
- {
- signedOrder,
- takerTokenFillAmount: partialFillTakerAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount: partialFillTakerAmount,
- },
- ];
- await zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress);
- });
- describe('order transaction options', () => {
- let signedOrder: SignedOrder;
- let orderFillRequests: OrderFillRequest[];
- const fillableAmount = new BigNumber(5);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- orderFillRequests = [
- {
- signedOrder,
- takerTokenFillAmount: new BigNumber(0),
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
- shouldValidate: true,
- }),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
- shouldValidate: false,
- }),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- describe('#fillOrKillOrderAsync', () => {
- let signedOrder: SignedOrder;
- const fillableAmount = new BigNumber(5);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- });
- describe('successful fills', () => {
- it('should fill a valid order', async () => {
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- 0,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- 0,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount,
- );
- await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(takerTokenFillAmount),
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- takerTokenFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- takerTokenFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(takerTokenFillAmount),
- );
- });
- it('should partially fill a valid order', async () => {
- const partialFillAmount = new BigNumber(3);
- await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(partialFillAmount),
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- partialFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- partialFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(partialFillAmount),
- );
- });
- });
- describe('order transaction options', () => {
- const emptyFillableAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
- shouldValidate: true,
- }),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
- shouldValidate: false,
- }),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- });
- describe('fill order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const fillableAmount = new BigNumber(5);
- const takerTokenFillAmount = new BigNumber(5);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- before(async () => {
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- describe('#fillOrderAsync', () => {
- describe('successful fills', () => {
- it('should fill a valid order', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- 0,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- 0,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount,
- );
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- takerTokenFillAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(takerTokenFillAmount),
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- takerTokenFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- takerTokenFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(takerTokenFillAmount),
- );
- });
- it('should partially fill the valid order', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const partialFillAmount = new BigNumber(3);
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- partialFillAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(partialFillAmount),
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal(
- partialFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal(
- partialFillAmount,
- );
- expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal(
- fillableAmount.minus(partialFillAmount),
- );
- });
- it('should fill the valid orders with fees', async () => {
- const makerFee = new BigNumber(1);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- takerAddress,
- fillableAmount,
- feeRecipient,
- );
- const txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- takerTokenFillAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient)).to.be.bignumber.equal(
- makerFee.plus(takerFee),
- );
- });
- });
- describe('order transaction options', () => {
- let signedOrder: SignedOrder;
- const emptyFillTakerAmount = new BigNumber(0);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.fillOrderAsync(
- signedOrder,
- emptyFillTakerAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrderAsync(
- signedOrder,
- emptyFillTakerAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: true,
- },
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrderAsync(
- signedOrder,
- emptyFillTakerAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: false,
- },
- ),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- describe('negative fill amount', async () => {
- let signedOrder: SignedOrder;
- const negativeFillTakerAmount = new BigNumber(-100);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- });
- it('should not allow the exchange wrapper to fill if amount is negative', async () => {
- return expect(
- zeroEx.exchange.fillOrderAsync(
- signedOrder,
- negativeFillTakerAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejected();
- });
- });
- });
- describe('#batchFillOrdersAsync', () => {
- let signedOrder: SignedOrder;
- let signedOrderHashHex: string;
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let orderFillBatch: OrderFillRequest[];
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- });
- describe('successful batch fills', () => {
- beforeEach(() => {
- orderFillBatch = [
- {
- signedOrder,
- takerTokenFillAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount,
- },
- ];
- });
- it('should throw if a batch is empty', async () => {
- return expect(
- zeroEx.exchange.batchFillOrdersAsync(
- [],
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- });
- it('should successfully fill multiple orders', async () => {
- const txHash = await zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(takerTokenFillAmount);
- expect(anotherFilledAmount).to.be.bignumber.equal(takerTokenFillAmount);
- });
- });
- describe('order transaction options', () => {
- beforeEach(async () => {
- const emptyFillTakerAmount = new BigNumber(0);
- orderFillBatch = [
- {
- signedOrder,
- takerTokenFillAmount: emptyFillTakerAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount: emptyFillTakerAmount,
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: true,
- },
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: false,
- },
- ),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- describe('negative batch fill amount', async () => {
- beforeEach(async () => {
- const negativeFillTakerAmount = new BigNumber(-100);
- orderFillBatch = [
- {
- signedOrder,
- takerTokenFillAmount,
- },
- {
- signedOrder: anotherSignedOrder,
- takerTokenFillAmount: negativeFillTakerAmount,
- },
- ];
- });
- it('should not allow the exchange wrapper to batch fill if any amount is negative', async () => {
- return expect(
- zeroEx.exchange.batchFillOrdersAsync(
- orderFillBatch,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejected();
- });
- });
- });
- describe('#fillOrdersUpTo', () => {
- let signedOrder: SignedOrder;
- let signedOrderHashHex: string;
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let signedOrders: SignedOrder[];
- const fillUpToAmount = fillableAmount.plus(fillableAmount).minus(1);
- beforeEach(async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- signedOrders = [signedOrder, anotherSignedOrder];
- });
- describe('successful batch fills', () => {
- it('should throw if a batch is empty', async () => {
- return expect(
- zeroEx.exchange.fillOrdersUpToAsync(
- [],
- fillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
- });
- it('should successfully fill up to specified amount when all orders are fully funded', async () => {
- const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- fillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(fillableAmount);
- const remainingFillAmount = fillableAmount.minus(1);
- expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
- });
- it('should successfully fill up to specified amount and leave the rest of the orders untouched', async () => {
- const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const zeroAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(fillableAmount);
- expect(zeroAmount).to.be.bignumber.equal(0);
- });
- it('should successfully fill up to specified amount even if filling all orders would fail', async () => {
- const missingBalance = new BigNumber(1); // User will still have enough balance to fill up to 9,
- // but won't have 10 to fully fill all orders in a batch.
- await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance);
- const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- fillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
- const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
- expect(filledAmount).to.be.bignumber.equal(fillableAmount);
- const remainingFillAmount = fillableAmount.minus(1);
- expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
- });
- });
- describe('failed batch fills', () => {
- it("should fail validation if user doesn't have enough balance without fill up to", async () => {
- const missingBalance = new BigNumber(2); // User will only have enough balance to fill up to 8
- await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance);
- return expect(
- zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- fillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
- });
- });
- describe('order transaction options', () => {
- const emptyFillUpToAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- emptyFillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- emptyFillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: true,
- },
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.fillOrdersUpToAsync(
- signedOrders,
- emptyFillUpToAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- {
- shouldValidate: false,
- },
- ),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- });
- });
- });
- describe('cancel order(s)', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- let signedOrder: SignedOrder;
- let orderHashHex: string;
- const cancelAmount = new BigNumber(3);
- beforeEach(async () => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
- });
- describe('#cancelOrderAsync', () => {
- describe('successful cancels', () => {
- it('should cancel an order', async () => {
- const txHash = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex);
- expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
- });
- });
- describe('order transaction options', () => {
- const emptyCancelTakerTokenAmount = new BigNumber(0);
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(
- zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
- shouldValidate: true,
- }),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
- shouldValidate: false,
- }),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- });
- });
- describe('#batchCancelOrdersAsync', () => {
- let anotherSignedOrder: SignedOrder;
- let anotherOrderHashHex: string;
- let cancelBatch: OrderCancellationRequest[];
- beforeEach(async () => {
- anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
- cancelBatch = [
- {
- order: signedOrder,
- takerTokenCancelAmount: cancelAmount,
- },
- {
- order: anotherSignedOrder,
- takerTokenCancelAmount: cancelAmount,
- },
- ];
- });
- describe('failed batch cancels', () => {
- it('should throw when orders have different makers', async () => {
- const signedOrderWithDifferentMaker = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- takerAddress,
- takerAddress,
- fillableAmount,
- );
- return expect(
- zeroEx.exchange.batchCancelOrdersAsync([
- cancelBatch[0],
- {
- order: signedOrderWithDifferentMaker,
- takerTokenCancelAmount: cancelAmount,
- },
- ]),
- ).to.be.rejectedWith(ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
- });
- });
- describe('successful batch cancels', () => {
- it('should cancel a batch of orders', async () => {
- await zeroEx.exchange.batchCancelOrdersAsync(cancelBatch);
- const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex);
- const anotherCancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(
- anotherOrderHashHex,
- );
- expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
- expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount);
- });
- });
- describe('order transaction options', () => {
- beforeEach(async () => {
- const emptyTakerTokenCancelAmount = new BigNumber(0);
- cancelBatch = [
- {
- order: signedOrder,
- takerTokenCancelAmount: emptyTakerTokenCancelAmount,
- },
- {
- order: anotherSignedOrder,
- takerTokenCancelAmount: emptyTakerTokenCancelAmount,
- },
- ];
- });
- it('should validate when orderTransactionOptions are not present', async () => {
- return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch)).to.be.rejectedWith(
- ExchangeContractErrs.OrderCancelAmountZero,
- );
- });
- it('should validate when orderTransactionOptions specify to validate', async () => {
- return expect(
- zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
- shouldValidate: true,
- }),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should not validate when orderTransactionOptions specify not to validate', async () => {
- return expect(
- zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
- shouldValidate: false,
- }),
- ).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- });
- });
- });
- describe('tests that require partially filled order', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let takerAddress: string;
- let fillableAmount: BigNumber;
- let partialFillAmount: BigNumber;
- let signedOrder: SignedOrder;
- let orderHash: string;
- before(() => {
- takerAddress = userAddresses[1];
- tokenUtils = new TokenUtils(tokens);
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- fillableAmount = new BigNumber(5);
- partialFillAmount = new BigNumber(2);
- signedOrder = await fillScenarios.createPartiallyFilledSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- takerAddress,
- fillableAmount,
- partialFillAmount,
- );
- orderHash = ZeroEx.getOrderHashHex(signedOrder);
- });
- describe('#getUnavailableTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
- expect(unavailableValueT).to.be.bignumber.equal(0);
- });
- it('should return the unavailableValueT for a valid and partially filled orderHash', async () => {
- const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
- expect(unavailableValueT).to.be.bignumber.equal(partialFillAmount);
- });
- });
- describe('#getFilledTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
- expect(filledValueT).to.be.bignumber.equal(0);
- });
- it('should return the filledValueT for a valid and partially filled orderHash', async () => {
- const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash);
- expect(filledValueT).to.be.bignumber.equal(partialFillAmount);
- });
- });
- describe('#getCancelledTakerAmountAsync', () => {
- it('should throw if passed an invalid orderHash', async () => {
- const invalidOrderHashHex = '0x123';
- return expect(zeroEx.exchange.getCancelledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
- });
- it('should return zero if passed a valid but non-existent orderHash', async () => {
- const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
- expect(cancelledValueT).to.be.bignumber.equal(0);
- });
- it('should return the cancelledValueT for a valid and partially filled orderHash', async () => {
- const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash);
- expect(cancelledValueT).to.be.bignumber.equal(0);
- });
- it('should return the cancelledValueT for a valid and cancelled orderHash', async () => {
- const cancelAmount = fillableAmount.minus(partialFillAmount);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
- const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash);
- expect(cancelledValueT).to.be.bignumber.equal(cancelAmount);
- });
- });
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let takerAddress: string;
- let makerAddress: string;
- let fillableAmount: BigNumber;
- let signedOrder: SignedOrder;
- const takerTokenFillAmountInBaseUnits = new BigNumber(1);
- const cancelTakerAmountInBaseUnits = new BigNumber(1);
- before(() => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- fillableAmount = new BigNumber(5);
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- });
- afterEach(async () => {
- zeroEx.exchange.unsubscribeAll();
- });
- // Hack: Mocha does not allow a test to be both async and have a `done` callback
- // Since we need to await the receipt of the event in the `subscribe` callback,
- // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
- // wrap the rest of the test in an async block
- // Source: https://github.com/mochajs/mocha/issues/2407
- it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
- },
- );
- zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback);
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- takerTokenFillAmountInBaseUnits,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- })().catch(done);
- });
- it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<LogCancelContractEventArgs>) => {
- expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogCancel);
- },
- );
- zeroEx.exchange.subscribe(ExchangeEvents.LogCancel, indexFilterValues, callback);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
- })().catch(done);
- });
- it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled);
-
- const newProvider = web3Factory.getRpcProvider();
- zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
-
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
- },
- );
- zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback);
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- takerTokenFillAmountInBaseUnits,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- })().catch(done);
- });
- it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- const subscriptionToken = zeroEx.exchange.subscribe(
- ExchangeEvents.LogFill,
- indexFilterValues,
- callbackNeverToBeCalled,
- );
- zeroEx.exchange.unsubscribe(subscriptionToken);
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- takerTokenFillAmountInBaseUnits,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- done();
- })().catch(done);
- });
- });
- describe('#getOrderHashHexUsingContractCallAsync', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- before(async () => {
- [, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- it("get's the same hash as the local function", async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- const orderHashFromContract = await (zeroEx.exchange as any)._getOrderHashHexUsingContractCallAsync(
- signedOrder,
- );
- expect(orderHash).to.equal(orderHashFromContract);
- });
- });
- describe('#getZRXTokenAddressAsync', () => {
- it('gets the same token as is in token registry', () => {
- const zrxAddress = zeroEx.exchange.getZRXTokenAddress();
- const zrxToken = tokenUtils.getProtocolTokenOrThrow();
- expect(zrxAddress).to.equal(zrxToken.address);
- });
- });
- describe('#getLogsAsync', () => {
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let makerAddress: string;
- let takerAddress: string;
- const fillableAmount = new BigNumber(5);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- const blockRange: BlockRange = {
- fromBlock: 0,
- toBlock: BlockParamLiteral.Latest,
- };
- let txHash: string;
- before(async () => {
- [, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- it('should get logs with decoded args emitted by LogFill', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = ExchangeEvents.LogFill;
- const indexFilterValues = {};
- const logs = await zeroEx.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
- expect(logs).to.have.length(1);
- expect(logs[0].event).to.be.equal(eventName);
- });
- it('should only get the logs with the correct event name', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const differentEventName = ExchangeEvents.LogCancel;
- const indexFilterValues = {};
- const logs = await zeroEx.exchange.getLogsAsync(differentEventName, blockRange, indexFilterValues);
- expect(logs).to.have.length(0);
- });
- it('should only get the logs with the correct indexed fields', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const differentMakerAddress = userAddresses[2];
- const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- differentMakerAddress,
- takerAddress,
- fillableAmount,
- );
- txHash = await zeroEx.exchange.fillOrderAsync(
- anotherSignedOrder,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- await zeroEx.awaitTransactionMinedAsync(txHash);
-
- const eventName = ExchangeEvents.LogFill;
- const indexFilterValues = {
- maker: differentMakerAddress,
- };
- const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(args.maker).to.be.equal(differentMakerAddress);
- });
- });
-}); // tslint:disable:max-file-line-count
diff --git a/packages/0x.js/test/expiration_watcher_test.ts b/packages/0x.js/test/expiration_watcher_test.ts
deleted file mode 100644
index ed7a6e5e3..000000000
--- a/packages/0x.js/test/expiration_watcher_test.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-import * as Sinon from 'sinon';
-import * as Web3 from 'web3';
-
-import { ZeroEx } from '../src/0x';
-import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher';
-import { DoneCallback, Token } from '../src/types';
-import { utils } from '../src/utils/utils';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { FillScenarios } from './utils/fill_scenarios';
-import { reportNoErrorCallbackErrors } from './utils/report_callback_errors';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('ExpirationWatcher', () => {
- let zeroEx: ZeroEx;
- let tokenUtils: TokenUtils;
- let tokens: Token[];
- let userAddresses: string[];
- let zrxTokenAddress: string;
- let fillScenarios: FillScenarios;
- let exchangeContractAddress: string;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const fillableAmount = new BigNumber(5);
- let currentUnixTimestampSec: BigNumber;
- let timer: Sinon.SinonFakeTimers;
- let expirationWatcher: ExpirationWatcher;
- before(async () => {
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- zeroEx = new ZeroEx(web3.currentProvider, config);
- exchangeContractAddress = zeroEx.exchange.getContractAddress();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- const sinonTimerConfig = { shouldAdvanceTime: true } as any;
- // This constructor has incorrect types
- timer = Sinon.useFakeTimers(sinonTimerConfig);
- currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
- expirationWatcher = new ExpirationWatcher();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- timer.restore();
- expirationWatcher.unsubscribe();
- });
- it('correctly emits events when order expires', (done: DoneCallback) => {
- (async () => {
- const orderLifetimeSec = 60;
- const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- expirationUnixTimestampSec,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
- const callbackAsync = reportNoErrorCallbackErrors(done)((hash: string) => {
- expect(hash).to.be.equal(orderHash);
- expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec);
- });
- expirationWatcher.subscribe(callbackAsync);
- timer.tick(orderLifetimeSec * 1000);
- })().catch(done);
- });
- it("doesn't emit events before order expires", (done: DoneCallback) => {
- (async () => {
- const orderLifetimeSec = 60;
- const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- expirationUnixTimestampSec,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
- const callbackAsync = reportNoErrorCallbackErrors(done)(async (hash: string) => {
- done(new Error('Emitted expiration went before the order actually expired'));
- });
- expirationWatcher.subscribe(callbackAsync);
- const notEnoughTime = orderLifetimeSec - 1;
- timer.tick(notEnoughTime * 1000);
- done();
- })().catch(done);
- });
- it('emits events in correct order', (done: DoneCallback) => {
- (async () => {
- const order1Lifetime = 60;
- const order2Lifetime = 120;
- const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
- const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
- const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- order1ExpirationUnixTimestampSec,
- );
- const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- order2ExpirationUnixTimestampSec,
- );
- const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
- const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2);
- expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
- expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
- const expirationOrder = [orderHash1, orderHash2];
- const expectToBeCalledOnce = false;
- const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => {
- const orderHash = expirationOrder.shift();
- expect(hash).to.be.equal(orderHash);
- if (_.isEmpty(expirationOrder)) {
- done();
- }
- });
- expirationWatcher.subscribe(callbackAsync);
- timer.tick(order2Lifetime * 1000);
- })().catch(done);
- });
-});
diff --git a/packages/0x.js/test/global_hooks.ts b/packages/0x.js/test/global_hooks.ts
new file mode 100644
index 000000000..364828231
--- /dev/null
+++ b/packages/0x.js/test/global_hooks.ts
@@ -0,0 +1,17 @@
+import { devConstants } from '@0xproject/dev-utils';
+import { runV2MigrationsAsync } from '@0xproject/migrations';
+
+import { provider } from './utils/web3_wrapper';
+
+before('migrate contracts', async function(): Promise<void> {
+ // HACK: Since the migrations take longer then our global mocha timeout limit
+ // we manually increase it for this before hook.
+ const mochaTestTimeoutMs = 20000;
+ this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
+ const txDefaults = {
+ gas: devConstants.GAS_LIMIT,
+ from: devConstants.TESTRPC_FIRST_ADDRESS,
+ };
+ const artifactsDir = `../migrations/artifacts/2.0.0`;
+ await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
+});
diff --git a/packages/0x.js/test/order_state_watcher_test.ts b/packages/0x.js/test/order_state_watcher_test.ts
deleted file mode 100644
index 4210e013f..000000000
--- a/packages/0x.js/test/order_state_watcher_test.ts
+++ /dev/null
@@ -1,559 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-import * as Web3 from 'web3';
-
-import {
- ExchangeContractErrs,
- OrderState,
- OrderStateInvalid,
- OrderStateValid,
- SignedOrder,
- Token,
- ZeroEx,
- ZeroExError,
-} from '../src';
-import { OrderStateWatcher } from '../src/order_watcher/order_state_watcher';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { FillScenarios } from './utils/fill_scenarios';
-import { reportNodeCallbackErrors } from './utils/report_callback_errors';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-const TIMEOUT_MS = 150;
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('OrderStateWatcher', () => {
- let zeroEx: ZeroEx;
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let fillScenarios: FillScenarios;
- let userAddresses: string[];
- let zrxTokenAddress: string;
- let exchangeContractAddress: string;
- let makerToken: Token;
- let takerToken: Token;
- let maker: string;
- let taker: string;
- let signedOrder: SignedOrder;
- let orderStateWatcher: OrderStateWatcher;
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- const decimals = constants.ZRX_DECIMALS;
- const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- orderStateWatcher = zeroEx.createOrderStateWatcher();
- exchangeContractAddress = zeroEx.exchange.getContractAddress();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [, maker, taker] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- await fillScenarios.initTokenBalancesAsync();
- [makerToken, takerToken] = tokenUtils.getDummyTokens();
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#removeOrder', async () => {
- it('should successfully remove existing order', async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
- expect((orderStateWatcher as any)._orderByOrderHash).to.include({
- [orderHash]: signedOrder,
- });
- let dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes;
- expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
- orderStateWatcher.removeOrder(orderHash);
- expect((orderStateWatcher as any)._orderByOrderHash).to.not.include({
- [orderHash]: signedOrder,
- });
- dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes;
- expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined();
- });
- it('should no-op when removing a non-existing order', async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- const nonExistentOrderHash = `0x${orderHash
- .substr(2)
- .split('')
- .reverse()
- .join('')}`;
- orderStateWatcher.removeOrder(nonExistentOrderHash);
- });
- });
- describe('#subscribe', async () => {
- afterEach(async () => {
- orderStateWatcher.unsubscribe();
- });
- it('should fail when trying to subscribe twice', async () => {
- orderStateWatcher.subscribe(_.noop);
- expect(() => orderStateWatcher.subscribe(_.noop)).to.throw(ZeroExError.SubscriptionAlreadyPresent);
- });
- });
- describe('tests with cleanup', async () => {
- afterEach(async () => {
- orderStateWatcher.unsubscribe();
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.removeOrder(orderHash);
- });
- it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
- })().catch(done);
- });
- it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- orderStateWatcher.addOrder(signedOrder);
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- throw new Error('OrderState callback fired for irrelevant order');
- });
- orderStateWatcher.subscribe(callback);
- const notTheMaker = userAddresses[0];
- const anyRecipient = taker;
- const transferAmount = new BigNumber(2);
- await zeroEx.token.transferAsync(makerToken.address, notTheMaker, anyRecipient, transferAmount);
- setTimeout(() => {
- done();
- }, TIMEOUT_MS);
- })().catch(done);
- });
- it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
- });
- orderStateWatcher.subscribe(callback);
- const anyRecipient = taker;
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance);
- })().catch(done);
- });
- it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
- });
- orderStateWatcher.subscribe(callback);
-
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillableAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- taker,
- );
- })().catch(done);
- });
- it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
- const fillAmountInBaseUnits = new BigNumber(2);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
- const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingFillable,
- );
- expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
- remainingFillable,
- );
- expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
- });
- orderStateWatcher.subscribe(callback);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillAmountInBaseUnits,
- shouldThrowOnInsufficientBalanceOrAllowance,
- taker,
- );
- })().catch(done);
- });
- it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => {
- (async () => {
- const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
- const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
- signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerToken.address,
- takerToken.address,
- makerFee,
- takerFee,
- maker,
- taker,
- fillableAmount,
- taker,
- );
- const callback = reportNodeCallbackErrors(done)();
- orderStateWatcher.addOrder(signedOrder);
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
- })().catch(done);
- });
- describe('remainingFillable(M|T)akerTokenAmount', () => {
- it('should calculate correct remaining fillable', (done: DoneCallback) => {
- (async () => {
- const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
- const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
- signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- makerFillableAmount,
- takerFillableAmount,
- );
- const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals),
- );
- expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
- ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals),
- );
- });
- orderStateWatcher.subscribe(callback);
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
- await zeroEx.exchange.fillOrderAsync(
- signedOrder,
- fillAmountInBaseUnits,
- shouldThrowOnInsufficientBalanceOrAllowance,
- taker,
- );
- })().catch(done);
- });
- it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
-
- const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- changedMakerApprovalAmount,
- );
- expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
- changedMakerApprovalAmount,
- );
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount);
- })().catch(done);
- });
- it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
-
- const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
-
- const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
- const transferAmount = makerBalance.sub(remainingAmount);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingAmount,
- );
- expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
- remainingAmount,
- );
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.transferAsync(makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
- })().catch(done);
- });
- it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
- (async () => {
- const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
- const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
- const feeRecipient = taker;
- signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerToken.address,
- takerToken.address,
- makerFee,
- takerFee,
- maker,
- taker,
- fillableAmount,
- feeRecipient,
- );
-
- const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
- const transferTokenAmount = makerFee.sub(remainingTokenAmount);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingTokenAmount,
- );
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount);
- })().catch(done);
- });
- it('should equal ratio amount when fee balance is lowered', (done: DoneCallback) => {
- (async () => {
- const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
- const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
- const feeRecipient = taker;
- signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerToken.address,
- takerToken.address,
- makerFee,
- takerFee,
- maker,
- taker,
- fillableAmount,
- feeRecipient,
- );
-
- const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
-
- const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
- const transferTokenAmount = makerFee.sub(remainingTokenAmount);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- remainingFeeAmount,
- );
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
- await zeroEx.token.transferAsync(
- makerToken.address,
- maker,
- ZeroEx.NULL_ADDRESS,
- transferTokenAmount,
- );
- })().catch(done);
- });
- it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
- (async () => {
- const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
- const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- const feeRecipient = taker;
- signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerToken.address,
- takerToken.address,
- makerFee,
- takerFee,
- maker,
- taker,
- fillableAmount,
- feeRecipient,
- );
-
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- const validOrderState = orderState as OrderStateValid;
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
- fillableAmount,
- );
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.token.setProxyAllowanceAsync(
- makerToken.address,
- maker,
- ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals),
- );
- })().catch(done);
- });
- });
- it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
- });
- orderStateWatcher.subscribe(callback);
-
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- })().catch(done);
- });
- it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => {
- (async () => {
- const remainingFillableAmountInBaseUnits = new BigNumber(100);
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.false();
- const invalidOrderState = orderState as OrderStateInvalid;
- expect(invalidOrderState.orderHash).to.be.equal(orderHash);
- expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.exchange.cancelOrderAsync(
- signedOrder,
- fillableAmount.minus(remainingFillableAmountInBaseUnits),
- );
- })().catch(done);
- });
- it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
- (async () => {
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerToken.address,
- takerToken.address,
- maker,
- taker,
- fillableAmount,
- );
-
- const cancelAmountInBaseUnits = new BigNumber(2);
- const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- orderStateWatcher.addOrder(signedOrder);
-
- const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
- expect(orderState.isValid).to.be.true();
- const validOrderState = orderState as OrderStateValid;
- expect(validOrderState.orderHash).to.be.equal(orderHash);
- const orderRelevantState = validOrderState.orderRelevantState;
- expect(orderRelevantState.cancelledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits);
- });
- orderStateWatcher.subscribe(callback);
- await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits);
- })().catch(done);
- });
- });
-}); // tslint:disable:max-file-line-count
diff --git a/packages/0x.js/test/order_validation_test.ts b/packages/0x.js/test/order_validation_test.ts
deleted file mode 100644
index 5472ca8f6..000000000
--- a/packages/0x.js/test/order_validation_test.ts
+++ /dev/null
@@ -1,473 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { BlockParamLiteral } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import * as Sinon from 'sinon';
-import * as Web3 from 'web3';
-
-import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
-import { TradeSide, TransferType } from '../src/types';
-import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
-import { OrderValidationUtils } from '../src/utils/order_validation_utils';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { FillScenarios } from './utils/fill_scenarios';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('OrderValidation', () => {
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let exchangeContractAddress: string;
- let zrxTokenAddress: string;
- let fillScenarios: FillScenarios;
- let makerTokenAddress: string;
- let takerTokenAddress: string;
- let coinbase: string;
- let makerAddress: string;
- let takerAddress: string;
- let feeRecipient: string;
- const fillableAmount = new BigNumber(5);
- const fillTakerAmount = new BigNumber(5);
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- exchangeContractAddress = zeroEx.exchange.getContractAddress();
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
- fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('validateOrderFillableOrThrowAsync', () => {
- it('should succeed if the order is fillable', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
- });
- it('should succeed if the order is asymmetric and fillable', async () => {
- const makerFillableAmount = fillableAmount;
- const takerFillableAmount = fillableAmount.minus(4);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- makerFillableAmount,
- takerFillableAmount,
- );
- await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
- });
- it('should throw when the order is fully filled or cancelled', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
- ExchangeContractErrs.OrderRemainingFillAmountZero,
- );
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- expirationInPast,
- );
- return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
- ExchangeContractErrs.OrderFillExpired,
- );
- });
- });
- describe('validateFillOrderAndThrowIfInvalidAsync', () => {
- it('should throw when the fill amount is zero', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const zeroFillAmount = new BigNumber(0);
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, zeroFillAmount, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
- });
- it('should throw when the signature is invalid', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- // 27 <--> 28
- signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
- ).to.be.rejectedWith(ZeroExError.InvalidSignature);
- });
- it('should throw when the order is fully filled or cancelled', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
- });
- it('should throw when sender is not a taker', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const nonTakerAddress = userAddresses[6];
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, nonTakerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- expirationInPast,
- );
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
- });
- it('should throw when there a rounding error would have occurred', async () => {
- const makerAmount = new BigNumber(3);
- const takerAmount = new BigNumber(5);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- makerAmount,
- takerAmount,
- );
- const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
- return expect(
- zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder,
- fillTakerAmountThatCausesRoundingError,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
- });
- });
- describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
- it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
- const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- const tooLargeFillAmount = new BigNumber(7);
- const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
- await zeroEx.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference);
- await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount);
- await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
- await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
-
- return expect(
- zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
- signedOrder,
- tooLargeFillAmount,
- takerAddress,
- ),
- ).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
- });
- });
- describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
- let signedOrder: SignedOrder;
- const cancelAmount = new BigNumber(3);
- beforeEach(async () => {
- [coinbase, makerAddress, takerAddress] = userAddresses;
- const [makerToken, takerToken] = tokenUtils.getDummyTokens();
- makerTokenAddress = makerToken.address;
- takerTokenAddress = takerToken.address;
- signedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- );
- });
- it('should throw when cancel amount is zero', async () => {
- const zeroCancelAmount = new BigNumber(0);
- return expect(
- zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
- });
- it('should throw when order is expired', async () => {
- const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
- const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- expirationInPast,
- );
- return expect(
- zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
- });
- it('should throw when order is already cancelled or filled', async () => {
- await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
- return expect(
- zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount),
- ).to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
- });
- });
- describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
- let exchangeTransferSimulator: ExchangeTransferSimulator;
- let transferFromAsync: Sinon.SinonSpy;
- const bigNumberMatch = (expected: BigNumber) => {
- return Sinon.match((value: BigNumber) => value.eq(expected));
- };
- beforeEach('create exchangeTransferSimulator', async () => {
- exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
- transferFromAsync = Sinon.spy();
- exchangeTransferSimulator.transferFromAsync = transferFromAsync as any;
- });
- it('should call exchangeTransferSimulator.transferFrom in a correct order', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- takerAddress,
- fillableAmount,
- feeRecipient,
- );
- await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator,
- signedOrder,
- fillableAmount,
- takerAddress,
- zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- expect(
- transferFromAsync
- .getCall(0)
- .calledWith(
- makerTokenAddress,
- makerAddress,
- takerAddress,
- bigNumberMatch(fillableAmount),
- TradeSide.Maker,
- TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(1)
- .calledWith(
- takerTokenAddress,
- takerAddress,
- makerAddress,
- bigNumberMatch(fillableAmount),
- TradeSide.Taker,
- TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(2)
- .calledWith(
- zrxTokenAddress,
- makerAddress,
- feeRecipient,
- bigNumberMatch(makerFee),
- TradeSide.Maker,
- TransferType.Fee,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(3)
- .calledWith(
- zrxTokenAddress,
- takerAddress,
- feeRecipient,
- bigNumberMatch(takerFee),
- TradeSide.Taker,
- TransferType.Fee,
- ),
- ).to.be.true();
- });
- it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(2);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- ZeroEx.NULL_ADDRESS,
- fillableAmount,
- feeRecipient,
- );
- await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator,
- signedOrder,
- fillableAmount,
- takerAddress,
- zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- expect(
- transferFromAsync
- .getCall(0)
- .calledWith(
- makerTokenAddress,
- makerAddress,
- takerAddress,
- bigNumberMatch(fillableAmount),
- TradeSide.Maker,
- TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(1)
- .calledWith(
- takerTokenAddress,
- takerAddress,
- makerAddress,
- bigNumberMatch(fillableAmount),
- TradeSide.Taker,
- TransferType.Trade,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(2)
- .calledWith(
- zrxTokenAddress,
- makerAddress,
- feeRecipient,
- bigNumberMatch(makerFee),
- TradeSide.Maker,
- TransferType.Fee,
- ),
- ).to.be.true();
- expect(
- transferFromAsync
- .getCall(3)
- .calledWith(
- zrxTokenAddress,
- takerAddress,
- feeRecipient,
- bigNumberMatch(takerFee),
- TradeSide.Taker,
- TransferType.Fee,
- ),
- ).to.be.true();
- });
- it('should correctly round the fillMakerTokenAmount', async () => {
- const makerTokenAmount = new BigNumber(3);
- const takerTokenAmount = new BigNumber(1);
- const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- makerTokenAmount,
- takerTokenAmount,
- );
- await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator,
- signedOrder,
- takerTokenAmount,
- takerAddress,
- zrxTokenAddress,
- );
- expect(transferFromAsync.callCount).to.be.equal(4);
- const makerFillAmount = transferFromAsync.getCall(0).args[3];
- expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount);
- });
- it('should correctly round the makerFeeAmount', async () => {
- const makerFee = new BigNumber(2);
- const takerFee = new BigNumber(4);
- const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- takerAddress,
- fillableAmount,
- ZeroEx.NULL_ADDRESS,
- );
- const fillTakerTokenAmount = fillableAmount.div(2).round(0);
- await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTransferSimulator,
- signedOrder,
- fillTakerTokenAmount,
- takerAddress,
- zrxTokenAddress,
- );
- const makerPartialFee = makerFee.div(2);
- const takerPartialFee = takerFee.div(2);
- expect(transferFromAsync.callCount).to.be.equal(4);
- const partialMakerFee = transferFromAsync.getCall(2).args[3];
- expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee);
- const partialTakerFee = transferFromAsync.getCall(3).args[3];
- expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
- });
- });
-});
diff --git a/packages/0x.js/test/remaining_fillable_calculator_test.ts b/packages/0x.js/test/remaining_fillable_calculator_test.ts
deleted file mode 100644
index d97402ef6..000000000
--- a/packages/0x.js/test/remaining_fillable_calculator_test.ts
+++ /dev/null
@@ -1,234 +0,0 @@
-import { ECSignature, SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import 'mocha';
-
-import { ZeroEx } from '../src/0x';
-import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
-
-import { chaiSetup } from './utils/chai_setup';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-describe('RemainingFillableCalculator', () => {
- let calculator: RemainingFillableCalculator;
- let signedOrder: SignedOrder;
- let transferrableMakerTokenAmount: BigNumber;
- let transferrableMakerFeeTokenAmount: BigNumber;
- let remainingMakerTokenAmount: BigNumber;
- let makerAmount: BigNumber;
- let takerAmount: BigNumber;
- let makerFeeAmount: BigNumber;
- let isMakerTokenZRX: boolean;
- const makerToken: string = '0x1';
- const takerToken: string = '0x2';
- const decimals: number = 4;
- const zero: BigNumber = new BigNumber(0);
- const zeroAddress = '0x0';
- const signature: ECSignature = { v: 27, r: '', s: '' };
- beforeEach(async () => {
- [makerAmount, takerAmount, makerFeeAmount] = [
- ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals),
- ];
- [transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
- ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
- ];
- });
- function buildSignedOrder(): SignedOrder {
- return {
- ecSignature: signature,
- exchangeContractAddress: zeroAddress,
- feeRecipient: zeroAddress,
- maker: zeroAddress,
- taker: zeroAddress,
- makerFee: makerFeeAmount,
- takerFee: zero,
- makerTokenAmount: makerAmount,
- takerTokenAmount: takerAmount,
- makerTokenAddress: makerToken,
- takerTokenAddress: takerToken,
- salt: zero,
- expirationUnixTimestampSec: zero,
- };
- }
- describe('Maker token is NOT ZRX', () => {
- before(async () => {
- isMakerTokenZRX = false;
- });
- it('calculates the correct amount when unfilled and funds available', () => {
- signedOrder = buildSignedOrder();
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
- });
- it('calculates the correct amount when partially filled and funds available', () => {
- signedOrder = buildSignedOrder();
- remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
- });
- it('calculates the amount to be 0 when all fee funds are transferred', () => {
- signedOrder = buildSignedOrder();
- transferrableMakerFeeTokenAmount = zero;
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
- });
- it('calculates the correct amount when balance is less than remaining fillable', () => {
- signedOrder = buildSignedOrder();
- const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
- transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
- });
- describe('Order to Fee Ratio is < 1', () => {
- beforeEach(async () => {
- [makerAmount, takerAmount, makerFeeAmount] = [
- ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
- ];
- });
- it('calculates the correct amount when funds unavailable', () => {
- signedOrder = buildSignedOrder();
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
- });
- });
- describe('Ratio is not evenly divisble', () => {
- beforeEach(async () => {
- [makerAmount, takerAmount, makerFeeAmount] = [
- ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
- ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
- ];
- });
- it('calculates the correct amount when funds unavailable', () => {
- signedOrder = buildSignedOrder();
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
- expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakerTokenAmount)).to.be.true();
- expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0));
- const orderToFeeRatio = signedOrder.makerTokenAmount.dividedBy(signedOrder.makerFee);
- const calculatedFeeAmount = calculatedFillableAmount.dividedBy(orderToFeeRatio);
- expect(calculatedFeeAmount).to.be.bignumber.lessThan(transferrableMakerFeeTokenAmount);
- });
- });
- });
- describe('Maker Token is ZRX', () => {
- before(async () => {
- isMakerTokenZRX = true;
- });
- it('calculates the correct amount when unfilled and funds available', () => {
- signedOrder = buildSignedOrder();
- transferrableMakerTokenAmount = makerAmount.plus(makerFeeAmount);
- transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
- });
- it('calculates the correct amount when partially filled and funds available', () => {
- signedOrder = buildSignedOrder();
- remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
- });
- it('calculates the amount to be 0 when all fee funds are transferred', () => {
- signedOrder = buildSignedOrder();
- transferrableMakerTokenAmount = zero;
- transferrableMakerFeeTokenAmount = zero;
- remainingMakerTokenAmount = signedOrder.makerTokenAmount;
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
- });
- it('calculates the correct amount when balance is less than remaining fillable', () => {
- signedOrder = buildSignedOrder();
- const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
- remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
- transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
- transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
-
- const orderToFeeRatio = signedOrder.makerTokenAmount.dividedToIntegerBy(signedOrder.makerFee);
- const expectedFillableAmount = new BigNumber(450980);
- calculator = new RemainingFillableCalculator(
- signedOrder,
- isMakerTokenZRX,
- transferrableMakerTokenAmount,
- transferrableMakerFeeTokenAmount,
- remainingMakerTokenAmount,
- );
- const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
- const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio);
- const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio);
- expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(transferrableMakerTokenAmount);
- expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(remainingMakerTokenAmount);
- expect(calculatedFillableAmount).to.be.bignumber.equal(expectedFillableAmount);
- expect(numberOfFillsInRatio.decimalPlaces()).to.be.equal(0);
- });
- });
-});
diff --git a/packages/0x.js/test/subscription_test.ts b/packages/0x.js/test/subscription_test.ts
deleted file mode 100644
index 9b4751287..000000000
--- a/packages/0x.js/test/subscription_test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-import 'mocha';
-import * as Sinon from 'sinon';
-import * as Web3 from 'web3';
-
-import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { assertNodeCallbackError } from './utils/report_callback_errors';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('SubscriptionTest', () => {
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let coinbase: string;
- let addressWithoutFunds: string;
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- coinbase = userAddresses[0];
- addressWithoutFunds = userAddresses[1];
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- let tokenAddress: string;
- const allowanceAmount = new BigNumber(42);
- let stubs: Sinon.SinonStub[] = [];
- before(() => {
- const token = tokens[0];
- tokenAddress = token.address;
- });
- afterEach(() => {
- zeroEx.token.unsubscribeAll();
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => {
- (async () => {
- const errMsg = 'Error fetching block';
- const callback = assertNodeCallbackError(done, errMsg);
- stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))];
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
- })().catch(done);
- });
- it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => {
- (async () => {
- const errMsg = 'Error fetching logs';
- const callback = assertNodeCallbackError(done, errMsg);
- stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))];
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
- })().catch(done);
- });
- it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
- (async () => {
- const callback = (err: Error | null, logEvent?: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))];
- zeroEx.token.unsubscribeAll();
- done();
- })().catch(done);
- });
- });
-});
diff --git a/packages/0x.js/test/token_registry_wrapper_test.ts b/packages/0x.js/test/token_registry_wrapper_test.ts
deleted file mode 100644
index 3b7ce46fb..000000000
--- a/packages/0x.js/test/token_registry_wrapper_test.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { schemas, SchemaValidator } from '@0xproject/json-schemas';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-
-import { Token, ZeroEx } from '../src';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
-
-describe('TokenRegistryWrapper', () => {
- let zeroEx: ZeroEx;
- let tokens: Token[];
- const tokenAddressBySymbol: { [symbol: string]: string } = {};
- const tokenAddressByName: { [symbol: string]: string } = {};
- const tokenBySymbol: { [symbol: string]: Token } = {};
- const tokenByName: { [symbol: string]: Token } = {};
- const registeredSymbol = 'ZRX';
- const registeredName = '0x Protocol Token';
- const unregisteredSymbol = 'MAL';
- const unregisteredName = 'Malicious Token';
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- _.map(tokens, token => {
- tokenAddressBySymbol[token.symbol] = token.address;
- tokenAddressByName[token.name] = token.address;
- tokenBySymbol[token.symbol] = token;
- tokenByName[token.name] = token;
- });
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#getTokensAsync', () => {
- it('should return all the tokens added to the tokenRegistry during the migration', async () => {
- expect(tokens).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
-
- const schemaValidator = new SchemaValidator();
- _.each(tokens, token => {
- const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- });
- });
- });
- describe('#getTokenAddressesAsync', () => {
- it('should return all the token addresses added to the tokenRegistry during the migration', async () => {
- const tokenAddresses = await zeroEx.tokenRegistry.getTokenAddressesAsync();
- expect(tokenAddresses).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
-
- const schemaValidator = new SchemaValidator();
- _.each(tokenAddresses, tokenAddress => {
- const validationResult = schemaValidator.validate(tokenAddress, schemas.addressSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- expect(tokenAddress).to.not.be.equal(ZeroEx.NULL_ADDRESS);
- });
- });
- });
- describe('#getTokenAddressBySymbol', () => {
- it('should return correct address for a token in the registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(registeredSymbol);
- expect(tokenAddress).to.be.equal(tokenAddressBySymbol[registeredSymbol]);
- });
- it('should return undefined for a token out of registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(unregisteredSymbol);
- expect(tokenAddress).to.be.undefined();
- });
- });
- describe('#getTokenAddressByName', () => {
- it('should return correct address for a token in the registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(registeredName);
- expect(tokenAddress).to.be.equal(tokenAddressByName[registeredName]);
- });
- it('should return undefined for a token out of registry', async () => {
- const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(unregisteredName);
- expect(tokenAddress).to.be.undefined();
- });
- });
- describe('#getTokenBySymbol', () => {
- it('should return correct token for a token in the registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol);
- expect(token).to.be.deep.equal(tokenBySymbol[registeredSymbol]);
- });
- it('should return undefined for a token out of registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol);
- expect(token).to.be.undefined();
- });
- });
- describe('#getTokenByName', () => {
- it('should return correct token for a token in the registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(registeredName);
- expect(token).to.be.deep.equal(tokenByName[registeredName]);
- });
- it('should return undefined for a token out of registry', async () => {
- const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName);
- expect(token).to.be.undefined();
- });
- });
- describe('#getTokenIfExistsAsync', () => {
- it('should return the token added to the tokenRegistry during the migration', async () => {
- const aToken = tokens[0];
-
- const token = await zeroEx.tokenRegistry.getTokenIfExistsAsync(aToken.address);
- const schemaValidator = new SchemaValidator();
- const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
- expect(validationResult.errors).to.have.lengthOf(0);
- });
- it('should return return undefined when passed a token address not in the tokenRegistry', async () => {
- const unregisteredTokenAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
- const tokenIfExists = await zeroEx.tokenRegistry.getTokenIfExistsAsync(unregisteredTokenAddress);
- expect(tokenIfExists).to.be.undefined();
- });
- });
-});
diff --git a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts b/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts
deleted file mode 100644
index fb003634a..000000000
--- a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { web3Factory } from '@0xproject/dev-utils';
-import * as chai from 'chai';
-
-import { ZeroEx } from '../src';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const web3 = web3Factory.create();
-
-describe('TokenTransferProxyWrapper', () => {
- let zeroEx: ZeroEx;
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- });
- describe('#isAuthorizedAsync', () => {
- it('should return false if the address is not authorized', async () => {
- const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(ZeroEx.NULL_ADDRESS);
- expect(isAuthorized).to.be.false();
- });
- });
- describe('#getAuthorizedAddressesAsync', () => {
- it('should return the list of authorized addresses', async () => {
- const authorizedAddresses = await zeroEx.proxy.getAuthorizedAddressesAsync();
- for (const authorizedAddress of authorizedAddresses) {
- const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(authorizedAddress);
- expect(isAuthorized).to.be.true();
- }
- });
- });
-});
diff --git a/packages/0x.js/test/token_wrapper_test.ts b/packages/0x.js/test/token_wrapper_test.ts
deleted file mode 100644
index 0c6335d5e..000000000
--- a/packages/0x.js/test/token_wrapper_test.ts
+++ /dev/null
@@ -1,517 +0,0 @@
-import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as chai from 'chai';
-import 'mocha';
-import * as Web3 from 'web3';
-
-import {
- ApprovalContractEventArgs,
- BlockParamLiteral,
- BlockRange,
- DecodedLogEvent,
- Token,
- TokenEvents,
- TransferContractEventArgs,
- ZeroEx,
- ZeroExError,
-} from '../src';
-import { DoneCallback } from '../src/types';
-
-import { chaiSetup } from './utils/chai_setup';
-import { constants } from './utils/constants';
-import { reportNodeCallbackErrors } from './utils/report_callback_errors';
-import { TokenUtils } from './utils/token_utils';
-import { web3, web3Wrapper } from './utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('TokenWrapper', () => {
- let zeroEx: ZeroEx;
- let userAddresses: string[];
- let tokens: Token[];
- let tokenUtils: TokenUtils;
- let coinbase: string;
- let addressWithoutFunds: string;
- const config = {
- networkId: constants.TESTRPC_NETWORK_ID,
- };
- before(async () => {
- zeroEx = new ZeroEx(web3.currentProvider, config);
- userAddresses = await zeroEx.getAvailableAddressesAsync();
- tokens = await zeroEx.tokenRegistry.getTokensAsync();
- tokenUtils = new TokenUtils(tokens);
- coinbase = userAddresses[0];
- addressWithoutFunds = userAddresses[1];
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('#transferAsync', () => {
- let token: Token;
- let transferAmount: BigNumber;
- before(() => {
- token = tokens[0];
- transferAmount = new BigNumber(42);
- });
- it('should successfully transfer tokens', async () => {
- const fromAddress = coinbase;
- const toAddress = addressWithoutFunds;
- const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- expect(preBalance).to.be.bignumber.equal(0);
- await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
- const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- return expect(postBalance).to.be.bignumber.equal(transferAmount);
- });
- it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
- const fromAddress = addressWithoutFunds;
- const toAddress = coinbase;
- return expect(
- zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount),
- ).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- const fromAddress = coinbase;
- const toAddress = coinbase;
- return expect(
- zeroEx.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount),
- ).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
- });
- });
- describe('#transferFromAsync', () => {
- let token: Token;
- let toAddress: string;
- let senderAddress: string;
- before(async () => {
- token = tokens[0];
- toAddress = addressWithoutFunds;
- senderAddress = userAddresses[2];
- });
- it('should fail to transfer tokens if fromAddress has insufficient allowance set', async () => {
- const fromAddress = coinbase;
- const transferAmount = new BigNumber(42);
-
- const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
- expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
-
- const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress, toAddress);
- expect(fromAddressAllowance).to.be.bignumber.equal(0);
-
- return expect(
- zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
- ).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
- });
- it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => {
- const fromAddress = coinbase;
- const transferAmount = new BigNumber(42);
-
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
-
- return expect(
- zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
- ).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
- });
- it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
- const fromAddress = addressWithoutFunds;
- const transferAmount = new BigNumber(42);
-
- const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
- expect(fromAddressBalance).to.be.bignumber.equal(0);
-
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
- const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(
- token.address,
- fromAddress,
- senderAddress,
- );
- expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
-
- return expect(
- zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
- ).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
- });
- it('should successfully transfer tokens', async () => {
- const fromAddress = coinbase;
-
- const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- expect(preBalance).to.be.bignumber.equal(0);
-
- const transferAmount = new BigNumber(42);
- await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
-
- await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount);
- const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
- return expect(postBalance).to.be.bignumber.equal(transferAmount);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const fromAddress = coinbase;
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- return expect(
- zeroEx.token.transferFromAsync(
- nonExistentTokenAddress,
- fromAddress,
- toAddress,
- senderAddress,
- new BigNumber(42),
- ),
- ).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
- });
- });
- describe('#getBalanceAsync', () => {
- describe('With web3 provider with accounts', () => {
- it('should return the balance for an existing ERC20 token', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const balance = await zeroEx.token.getBalanceAsync(token.address, ownerAddress);
- const expectedBalance = new BigNumber('1000000000000000000000000000');
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
- const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
- const ownerAddress = coinbase;
- return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress)).to.be.rejectedWith(
- ZeroExError.TokenContractDoesNotExist,
- );
- });
- it('should return a balance of 0 for a non-existent owner address', async () => {
- const token = tokens[0];
- const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
- const balance = await zeroEx.token.getBalanceAsync(token.address, nonExistentOwner);
- const expectedBalance = new BigNumber(0);
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- });
- describe('With web3 provider without accounts', () => {
- let zeroExWithoutAccounts: ZeroEx;
- before(async () => {
- const hasAddresses = false;
- const web3WithoutAccounts = web3Factory.create({ hasAddresses });
- zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
- });
- it('should return balance even when called with Web3 provider instance without addresses', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
- const expectedBalance = new BigNumber('1000000000000000000000000000');
- return expect(balance).to.be.bignumber.equal(expectedBalance);
- });
- });
- });
- describe('#setAllowanceAsync', () => {
- it("should set the spender's allowance", async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(
- token.address,
- ownerAddress,
- spenderAddress,
- );
- const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
- expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowanceAfterSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
- return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
- });
- });
- describe('#setUnlimitedAllowanceAsync', () => {
- it("should set the unlimited spender's allowance", async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- await zeroEx.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
- const transferAmount = new BigNumber(5);
- const zrx = tokenUtils.getProtocolTokenOrThrow();
- const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
- await zeroEx.token.setAllowanceAsync(zrx.address, coinbase, userWithNormalAllowance, transferAmount);
- await zeroEx.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance);
-
- const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
- const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
- userWithUnlimitedAllowance,
- );
-
- await zeroEx.token.transferFromAsync(
- zrx.address,
- coinbase,
- userWithNormalAllowance,
- userWithNormalAllowance,
- transferAmount,
- );
- await zeroEx.token.transferFromAsync(
- zrx.address,
- coinbase,
- userWithUnlimitedAllowance,
- userWithUnlimitedAllowance,
- transferAmount,
- );
-
- const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
- const finalBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
- userWithUnlimitedAllowance,
- );
-
- const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance);
- const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance);
-
- // In theory the gas cost with unlimited allowance should be smaller, but with testrpc it's actually bigger.
- // This needs to be investigated in ethereumjs-vm. This test is essentially a repro.
- // TODO: Make this test pass with inverted assertion.
- expect(unlimitedGasCost.toNumber()).to.be.gt(normalGasCost.toNumber());
- });
- });
- describe('#getAllowanceAsync', () => {
- describe('With web3 provider with accounts', () => {
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- it('should return 0 if no allowance set yet', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
- const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
- const expectedAllowance = new BigNumber(0);
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- describe('With web3 provider without accounts', () => {
- let zeroExWithoutAccounts: ZeroEx;
- before(async () => {
- const hasAddresses = false;
- const web3WithoutAccounts = web3Factory.create({ hasAddresses });
- zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
- });
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
- const spenderAddress = addressWithoutFunds;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
-
- const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
- token.address,
- ownerAddress,
- spenderAddress,
- );
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- });
- describe('#getProxyAllowanceAsync', () => {
- it('should get the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
-
- const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowance = amountInBaseUnits;
- return expect(allowance).to.be.bignumber.equal(expectedAllowance);
- });
- });
- describe('#setProxyAllowanceAsync', () => {
- it('should set the proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- const allowanceBeforeSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
- expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
-
- const amountInBaseUnits = new BigNumber(50);
- await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
-
- const allowanceAfterSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
- return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
- });
- });
- describe('#setUnlimitedProxyAllowanceAsync', () => {
- it('should set the unlimited proxy allowance', async () => {
- const token = tokens[0];
- const ownerAddress = coinbase;
-
- await zeroEx.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress);
- const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
- return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- });
- describe('#subscribe', () => {
- const indexFilterValues = {};
- let tokenAddress: string;
- const transferAmount = new BigNumber(42);
- const allowanceAmount = new BigNumber(42);
- before(() => {
- const token = tokens[0];
- tokenAddress = token.address;
- });
- afterEach(() => {
- zeroEx.token.unsubscribeAll();
- });
- // Hack: Mocha does not allow a test to be both async and have a `done` callback
- // Since we need to await the receipt of the event in the `subscribe` callback,
- // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
- // wrap the rest of the test in an async block
- // Source: https://github.com/mochajs/mocha/issues/2407
- it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
- expect(logEvent.isRemoved).to.be.false();
- expect(logEvent.log.logIndex).to.be.equal(0);
- expect(logEvent.log.transactionIndex).to.be.equal(0);
- expect(logEvent.log.blockNumber).to.be.a('number');
- const args = logEvent.log.args;
- expect(args._from).to.be.equal(coinbase);
- expect(args._to).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(transferAmount);
- },
- );
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- })().catch(done);
- });
- it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
- (async () => {
- const callback = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- expect(logEvent).to.not.be.undefined();
- expect(logEvent.isRemoved).to.be.false();
- const args = logEvent.log.args;
- expect(args._owner).to.be.equal(coinbase);
- expect(args._spender).to.be.equal(addressWithoutFunds);
- expect(args._value).to.be.bignumber.equal(allowanceAmount);
- },
- );
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
- await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
- })().catch(done);
- });
- it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
- const callbackToBeCalled = reportNodeCallbackErrors(done)();
- const newProvider = web3Factory.getRpcProvider();
- zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
- zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled);
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- })().catch(done);
- });
- it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
- (async () => {
- const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
- (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
- done(new Error('Expected this subscription to have been cancelled'));
- },
- );
- const subscriptionToken = zeroEx.token.subscribe(
- tokenAddress,
- TokenEvents.Transfer,
- indexFilterValues,
- callbackNeverToBeCalled,
- );
- zeroEx.token.unsubscribe(subscriptionToken);
- await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
- done();
- })().catch(done);
- });
- });
- describe('#getLogsAsync', () => {
- let tokenAddress: string;
- let tokenTransferProxyAddress: string;
- const blockRange: BlockRange = {
- fromBlock: 0,
- toBlock: BlockParamLiteral.Latest,
- };
- let txHash: string;
- before(() => {
- const token = tokens[0];
- tokenAddress = token.address;
- tokenTransferProxyAddress = zeroEx.proxy.getContractAddress();
- });
- it('should get logs with decoded args emitted by Approval', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = TokenEvents.Approval;
- const indexFilterValues = {};
- const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
- tokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(logs[0].event).to.be.equal(eventName);
- expect(args._owner).to.be.equal(coinbase);
- expect(args._spender).to.be.equal(tokenTransferProxyAddress);
- expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
- });
- it('should only get the logs with the correct event name', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const differentEventName = TokenEvents.Transfer;
- const indexFilterValues = {};
- const logs = await zeroEx.token.getLogsAsync(
- tokenAddress,
- differentEventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(0);
- });
- it('should only get the logs with the correct indexed fields', async () => {
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds);
- await zeroEx.awaitTransactionMinedAsync(txHash);
- const eventName = TokenEvents.Approval;
- const indexFilterValues = {
- _owner: coinbase,
- };
- const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
- tokenAddress,
- eventName,
- blockRange,
- indexFilterValues,
- );
- expect(logs).to.have.length(1);
- const args = logs[0].args;
- expect(args._owner).to.be.equal(coinbase);
- });
- });
-});
-// tslint:disable:max-file-line-count
diff --git a/packages/0x.js/test/utils/chai_setup.ts b/packages/0x.js/test/utils/chai_setup.ts
index 078edd309..1a8733093 100644
--- a/packages/0x.js/test/utils/chai_setup.ts
+++ b/packages/0x.js/test/utils/chai_setup.ts
@@ -4,7 +4,7 @@ import ChaiBigNumber = require('chai-bignumber');
import * as dirtyChai from 'dirty-chai';
export const chaiSetup = {
- configure() {
+ configure(): void {
chai.config.includeStack = true;
chai.use(ChaiBigNumber());
chai.use(dirtyChai);
diff --git a/packages/0x.js/test/utils/fill_scenarios.ts b/packages/0x.js/test/utils/fill_scenarios.ts
deleted file mode 100644
index 8b1308298..000000000
--- a/packages/0x.js/test/utils/fill_scenarios.ts
+++ /dev/null
@@ -1,198 +0,0 @@
-import { BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-
-import { SignedOrder, Token, ZeroEx } from '../../src';
-import { artifacts } from '../../src/artifacts';
-import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
-import { orderFactory } from '../utils/order_factory';
-
-import { constants } from './constants';
-
-const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
-
-export class FillScenarios {
- private _zeroEx: ZeroEx;
- private _userAddresses: string[];
- private _tokens: Token[];
- private _coinbase: string;
- private _zrxTokenAddress: string;
- private _exchangeContractAddress: string;
- constructor(
- zeroEx: ZeroEx,
- userAddresses: string[],
- tokens: Token[],
- zrxTokenAddress: string,
- exchangeContractAddress: string,
- ) {
- this._zeroEx = zeroEx;
- this._userAddresses = userAddresses;
- this._tokens = tokens;
- this._coinbase = userAddresses[0];
- this._zrxTokenAddress = zrxTokenAddress;
- this._exchangeContractAddress = exchangeContractAddress;
- }
- public async initTokenBalancesAsync() {
- const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
- for (const token of this._tokens) {
- if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
- const defaults = {};
- const dummyToken = new DummyTokenContract(web3Wrapper, artifacts.DummyTokenArtifact.abi, token.address);
- const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
- const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
- from: this._coinbase,
- });
- await this._zeroEx.awaitTransactionMinedAsync(txHash);
- }
- }
- }
- public async createFillableSignedOrderAsync(
- makerTokenAddress: string,
- takerTokenAddress: string,
- makerAddress: string,
- takerAddress: string,
- fillableAmount: BigNumber,
- expirationUnixTimestampSec?: BigNumber,
- ): Promise<SignedOrder> {
- return this.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- fillableAmount,
- expirationUnixTimestampSec,
- );
- }
- public async createFillableSignedOrderWithFeesAsync(
- makerTokenAddress: string,
- takerTokenAddress: string,
- makerFee: BigNumber,
- takerFee: BigNumber,
- makerAddress: string,
- takerAddress: string,
- fillableAmount: BigNumber,
- feeRecepient: string,
- expirationUnixTimestampSec?: BigNumber,
- ): Promise<SignedOrder> {
- return this._createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- takerAddress,
- fillableAmount,
- fillableAmount,
- feeRecepient,
- expirationUnixTimestampSec,
- );
- }
- public async createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress: string,
- takerTokenAddress: string,
- makerAddress: string,
- takerAddress: string,
- makerFillableAmount: BigNumber,
- takerFillableAmount: BigNumber,
- expirationUnixTimestampSec?: BigNumber,
- ): Promise<SignedOrder> {
- const makerFee = new BigNumber(0);
- const takerFee = new BigNumber(0);
- const feeRecepient = constants.NULL_ADDRESS;
- return this._createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerFee,
- takerFee,
- makerAddress,
- takerAddress,
- makerFillableAmount,
- takerFillableAmount,
- feeRecepient,
- expirationUnixTimestampSec,
- );
- }
- public async createPartiallyFilledSignedOrderAsync(
- makerTokenAddress: string,
- takerTokenAddress: string,
- takerAddress: string,
- fillableAmount: BigNumber,
- partialFillAmount: BigNumber,
- ) {
- const [makerAddress] = this._userAddresses;
- const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
- makerTokenAddress,
- takerTokenAddress,
- makerAddress,
- takerAddress,
- fillableAmount,
- fillableAmount,
- );
- const shouldThrowOnInsufficientBalanceOrAllowance = false;
- await this._zeroEx.exchange.fillOrderAsync(
- signedOrder,
- partialFillAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
- takerAddress,
- );
- return signedOrder;
- }
- private async _createAsymmetricFillableSignedOrderWithFeesAsync(
- makerTokenAddress: string,
- takerTokenAddress: string,
- makerFee: BigNumber,
- takerFee: BigNumber,
- makerAddress: string,
- takerAddress: string,
- makerFillableAmount: BigNumber,
- takerFillableAmount: BigNumber,
- feeRecepient: string,
- expirationUnixTimestampSec?: BigNumber,
- ): Promise<SignedOrder> {
- await Promise.all([
- this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
- this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
- ]);
- await Promise.all([
- this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
- this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
- ]);
-
- const signedOrder = await orderFactory.createSignedOrderAsync(
- this._zeroEx,
- makerAddress,
- takerAddress,
- makerFee,
- takerFee,
- makerFillableAmount,
- makerTokenAddress,
- takerFillableAmount,
- takerTokenAddress,
- this._exchangeContractAddress,
- feeRecepient,
- expirationUnixTimestampSec,
- );
- return signedOrder;
- }
- private async _increaseBalanceAndAllowanceAsync(
- tokenAddress: string,
- address: string,
- amount: BigNumber,
- ): Promise<void> {
- if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
- return; // noop
- }
- await Promise.all([
- this._increaseBalanceAsync(tokenAddress, address, amount),
- this._increaseAllowanceAsync(tokenAddress, address, amount),
- ]);
- }
- private async _increaseBalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
- await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
- }
- private async _increaseAllowanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
- const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
- const newMakerAllowance = oldMakerAllowance.plus(amount);
- await this._zeroEx.token.setProxyAllowanceAsync(tokenAddress, address, newMakerAllowance);
- }
-}
diff --git a/packages/0x.js/test/utils/order_factory.ts b/packages/0x.js/test/utils/order_factory.ts
deleted file mode 100644
index 08f2081a4..000000000
--- a/packages/0x.js/test/utils/order_factory.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
-
-import { SignedOrder, ZeroEx } from '../../src';
-
-const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
-
-export const orderFactory = {
- async createSignedOrderAsync(
- zeroEx: ZeroEx,
- maker: string,
- taker: string,
- makerFee: BigNumber,
- takerFee: BigNumber,
- makerTokenAmount: BigNumber,
- makerTokenAddress: string,
- takerTokenAmount: BigNumber,
- takerTokenAddress: string,
- exchangeContractAddress: string,
- feeRecipient: string,
- expirationUnixTimestampSecIfExists?: BigNumber,
- ): Promise<SignedOrder> {
- const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
- const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists)
- ? defaultExpirationUnixTimestampSec
- : expirationUnixTimestampSecIfExists;
- const order = {
- maker,
- taker,
- makerFee,
- takerFee,
- makerTokenAmount,
- takerTokenAmount,
- makerTokenAddress,
- takerTokenAddress,
- salt: ZeroEx.generatePseudoRandomSalt(),
- exchangeContractAddress,
- feeRecipient,
- expirationUnixTimestampSec,
- };
- const orderHash = ZeroEx.getOrderHashHex(order);
- const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX);
- const signedOrder: SignedOrder = _.assign(order, { ecSignature });
- return signedOrder;
- },
-};
diff --git a/packages/0x.js/test/utils/report_callback_errors.ts b/packages/0x.js/test/utils/report_callback_errors.ts
deleted file mode 100644
index 27c9745c9..000000000
--- a/packages/0x.js/test/utils/report_callback_errors.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import * as chai from 'chai';
-import * as _ from 'lodash';
-
-import { DoneCallback } from '../../src/types';
-
-const expect = chai.expect;
-
-export const reportNoErrorCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => {
- return <T>(f?: (value: T) => void) => {
- const wrapped = (value: T) => {
- if (_.isUndefined(f)) {
- done();
- return;
- }
- try {
- f(value);
- if (expectToBeCalledOnce) {
- done();
- }
- } catch (err) {
- done(err);
- }
- };
- return wrapped;
- };
-};
-
-export const reportNodeCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => {
- return <T>(f?: (value: T) => void) => {
- const wrapped = (error: Error | null, value: T | undefined) => {
- if (!_.isNull(error)) {
- done(error);
- } else {
- if (_.isUndefined(f)) {
- done();
- return;
- }
- try {
- f(value as T);
- if (expectToBeCalledOnce) {
- done();
- }
- } catch (err) {
- done(err);
- }
- }
- };
- return wrapped;
- };
-};
-
-export const assertNodeCallbackError = (done: DoneCallback, errMsg: string) => {
- const wrapped = <T>(error: Error | null, value: T | undefined) => {
- if (_.isNull(error)) {
- done(new Error('Expected callback to receive an error'));
- } else {
- try {
- expect(error.message).to.be.equal(errMsg);
- done();
- } catch (err) {
- done(err);
- }
- }
- };
- return wrapped;
-};
diff --git a/packages/0x.js/test/utils/token_utils.ts b/packages/0x.js/test/utils/token_utils.ts
index d3fc22ff4..a439c464d 100644
--- a/packages/0x.js/test/utils/token_utils.ts
+++ b/packages/0x.js/test/utils/token_utils.ts
@@ -1,33 +1,9 @@
-import * as _ from 'lodash';
+import { artifacts } from '../../src/artifacts';
-import { InternalZeroExError, Token } from '../../src/types';
+import { constants } from './constants';
-const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
-const WETH_TOKEN_SYMBOL = 'WETH';
-
-export class TokenUtils {
- private _tokens: Token[];
- constructor(tokens: Token[]) {
- this._tokens = tokens;
- }
- public getProtocolTokenOrThrow(): Token {
- const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
- if (_.isUndefined(zrxToken)) {
- throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
- }
- return zrxToken;
- }
- public getWethTokenOrThrow(): Token {
- const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
- if (_.isUndefined(wethToken)) {
- throw new Error(InternalZeroExError.WethNotInTokenRegistry);
- }
- return wethToken;
- }
- public getDummyTokens(): Token[] {
- const dummyTokens = _.filter(this._tokens, token => {
- return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol);
- });
- return dummyTokens;
- }
-}
+export const tokenUtils = {
+ getProtocolTokenAddress(): string {
+ return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
+ },
+};
diff --git a/packages/0x.js/test/utils/web3_wrapper.ts b/packages/0x.js/test/utils/web3_wrapper.ts
index 4b374fc7e..02c8c5918 100644
--- a/packages/0x.js/test/utils/web3_wrapper.ts
+++ b/packages/0x.js/test/utils/web3_wrapper.ts
@@ -1,6 +1,12 @@
-import { web3Factory } from '@0xproject/dev-utils';
+import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import * as Web3 from 'web3';
+import { Provider } from 'ethereum-types';
-export const web3 = web3Factory.create();
-export const web3Wrapper = new Web3Wrapper(web3.currentProvider);
+const txDefaults = {
+ from: devConstants.TESTRPC_FIRST_ADDRESS,
+ gas: devConstants.GAS_LIMIT,
+};
+const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true });
+const web3Wrapper = new Web3Wrapper(provider);
+
+export { provider, web3Wrapper, txDefaults };
diff --git a/packages/0x.js/tsconfig.json b/packages/0x.js/tsconfig.json
index ddf5a910e..e35816553 100644
--- a/packages/0x.js/tsconfig.json
+++ b/packages/0x.js/tsconfig.json
@@ -1,13 +1,7 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
- "outDir": "lib",
- "noImplicitThis": false
+ "outDir": "lib"
},
- "include": [
- "./src/**/*",
- "./test/**/*",
- "../../node_modules/types-bn/index.d.ts",
- "../../node_modules/types-ethereumjs-util/index.d.ts"
- ]
+ "include": ["./src/**/*", "./test/**/*"]
}