Compare commits
46 Commits
@0x/abi-ge
...
@0xproject
Author | SHA1 | Date | |
---|---|---|---|
|
8fb5c29b4b | ||
|
40a061a5ca | ||
|
2ef82592a3 | ||
|
14b5448d70 | ||
|
e7d45e47bf | ||
|
28268d4355 | ||
|
50fa02c1d1 | ||
|
b36ff9103d | ||
|
f032c2466c | ||
|
b63ddc9be4 | ||
|
171430b617 | ||
|
d561043774 | ||
|
b1871e9ddd | ||
|
b4a5e7258c | ||
|
3c75debdf9 | ||
|
84d1053f73 | ||
|
f9df42f5d9 | ||
|
4414ef0a0f | ||
|
b7729ada38 | ||
|
3da67feeb2 | ||
|
8a0d563a32 | ||
|
612fc4a949 | ||
|
bf915ce403 | ||
|
0f9ea9773e | ||
|
447a3a6c26 | ||
|
f1cc16c44d | ||
|
aae16b6343 | ||
|
834e1538d1 | ||
|
afc489bc2c | ||
|
3e061e7364 | ||
|
6395c2a8b2 | ||
|
c8225288cd | ||
|
4a108aa67d | ||
|
fd9b3e0dcf | ||
|
f94b647e61 | ||
|
2eccc3efaf | ||
|
972341725e | ||
|
40b10fd29d | ||
|
b31fcffc76 | ||
|
ec222ea0cd | ||
|
5533220da0 | ||
|
6ee7024457 | ||
|
f839ac9c58 | ||
|
1a8b1460a6 | ||
|
feac0779a4 | ||
|
d9eeb0421c |
@@ -1,398 +1,219 @@
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
environment:
|
||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
- run:
|
||||
name: install-yarn
|
||||
command: sudo npm install --global yarn@1.9.4
|
||||
- run:
|
||||
name: yarn
|
||||
command: yarn --frozen-lockfile install || yarn --frozen-lockfile install
|
||||
- run: yarn build:ci:no_website
|
||||
- run: yarn build:ts
|
||||
- save_cache:
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo
|
||||
build-website:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: cd packages/website && yarn build:prod
|
||||
test-contracts-ganache:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun test:circleci @0x/contracts-multisig
|
||||
- run: yarn wsrun test:circleci @0x/contracts-utils
|
||||
- run: yarn wsrun test:circleci @0x/contracts-libs
|
||||
- run: yarn wsrun test:circleci @0x/contracts-tokens
|
||||
- run: yarn wsrun test:circleci @0x/contracts-extensions
|
||||
- run: yarn wsrun test:circleci @0x/contracts-protocol
|
||||
test-contracts-geth:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
- image: 0xorg/devnet
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
|
||||
# initialized
|
||||
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test @0x/contracts-multisig
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-utils
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-libs
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-tokens
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-extensions
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-protocol
|
||||
test-publish:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
- image: 0xorg/verdaccio
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:publish:circleci
|
||||
test-doc-generation:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:generate_docs:circleci
|
||||
test-pipeline:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
- image: postgres:11-alpine
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: ZEROEX_DATA_PIPELINE_TEST_DB_URL='postgresql://postgres@localhost/postgres' yarn wsrun test:circleci @0x/pipeline
|
||||
- save_cache:
|
||||
key: coverage-pipeline-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/pipeline/coverage/lcov.info
|
||||
test-rest:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun test:circleci @0x/contracts-test-utils
|
||||
- run: yarn wsrun test:circleci @0x/abi-gen
|
||||
- run: yarn wsrun test:circleci @0x/assert
|
||||
- run: yarn wsrun test:circleci @0x/base-contract
|
||||
- run: yarn wsrun test:circleci @0x/connect
|
||||
- run: yarn wsrun test:circleci @0x/contract-wrappers
|
||||
- run: yarn wsrun test:circleci @0x/dev-utils
|
||||
- run: yarn wsrun test:circleci @0x/json-schemas
|
||||
- run: yarn wsrun test:circleci @0x/metacoin
|
||||
- run: yarn wsrun test:circleci @0x/order-utils
|
||||
- run: yarn wsrun test:circleci @0x/order-watcher
|
||||
- run: yarn wsrun test:circleci @0x/sol-compiler
|
||||
- run: yarn wsrun test:circleci @0x/sol-cov
|
||||
- run: yarn wsrun test:circleci @0x/sol-doc
|
||||
- run: yarn wsrun test:circleci @0x/subproviders
|
||||
- run: yarn wsrun test:circleci @0x/web3-wrapper
|
||||
- run: yarn wsrun test:circleci @0x/utils
|
||||
- run: yarn wsrun test:circleci @0x/instant
|
||||
- save_cache:
|
||||
key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/abi-gen/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/assert/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/base-contract/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/connect/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/contract-wrappers/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/dev-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/json-schemas/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/metacoin/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/order-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/order-watcher/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-compiler/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-cov/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-doc/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/subproviders/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/web3-wrapper/coverage/lcov.info
|
||||
test-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/python
|
||||
- image: 0xorg/ganache-cli
|
||||
command: |
|
||||
ganache-cli --gasLimit 10000000 --noVMErrorsOnRPCResponse --db /snapshot --noVMErrorsOnRPCResponse -p 8545 --networkId 50 -m "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
- image: 0xorg/launch-kit-ci
|
||||
command: |
|
||||
yarn start:ts -p 3000:3000
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python -m ensurepip
|
||||
python -m pip install -e .[dev]
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/sra_client
|
||||
python -m ensurepip
|
||||
python -m pip install -e .
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
- '.eggs'
|
||||
- '.mypy_cache'
|
||||
- '.pytest_cache'
|
||||
- '.tox'
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
coverage run setup.py test
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/sra_client
|
||||
coverage run setup.py test
|
||||
- save_cache:
|
||||
key: coverage-python-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/python-packages/order_utils/.coverage
|
||||
- save_cache:
|
||||
key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/python-packages/sra_client/.coverage
|
||||
test-rest-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/python
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python -m ensurepip
|
||||
python -m pip install -e .[dev]
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
- '.eggs'
|
||||
- '.mypy_cache'
|
||||
- '.pytest_cache'
|
||||
- '.tox'
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
tox
|
||||
static-tests-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/python
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python -m ensurepip
|
||||
python -m pip install -e .[dev]
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python setup.py lint
|
||||
static-tests:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn lerna run lint
|
||||
- run: yarn prettier:ci
|
||||
- run: cd packages/0x.js && yarn build:umd:prod
|
||||
- run: yarn bundlewatch
|
||||
submit-coverage:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-python-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn report_coverage
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
environment:
|
||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
- restore_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: yarn
|
||||
command: yarn --frozen-lockfile
|
||||
- save_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ./node_modules
|
||||
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
|
||||
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
|
||||
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
|
||||
- run: yarn build
|
||||
- save_cache:
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo
|
||||
test-installation:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:installation
|
||||
test-0xjs:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci 0x.js
|
||||
- save_cache:
|
||||
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/0x.js/coverage/lcov.info
|
||||
test-contracts:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci contracts
|
||||
- save_cache:
|
||||
key: coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/contracts/coverage/lcov.info
|
||||
test-sol-compiler:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci @0xproject/sol-compiler
|
||||
- save_cache:
|
||||
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-compiler/coverage/lcov.info
|
||||
test-rest:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci --exclude contracts --exclude 0x.js --exclude @0xproject/sol-compiler --stages --exclude-missing
|
||||
- save_cache:
|
||||
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/assert/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/connect/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/dev-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/json-schemas/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/subproviders/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-cov/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/metacoin/coverage/lcov.info
|
||||
lint:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn lerna:run lint
|
||||
prettier:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn prettier:ci
|
||||
submit-coverage:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn report_coverage
|
||||
workflows:
|
||||
version: 2
|
||||
main:
|
||||
jobs:
|
||||
version: 2
|
||||
main:
|
||||
jobs:
|
||||
- build
|
||||
- test-installation:
|
||||
requires:
|
||||
- build
|
||||
- build-website:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts-ganache:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts-geth:
|
||||
requires:
|
||||
- build
|
||||
- test-pipeline:
|
||||
requires:
|
||||
- build
|
||||
- test-rest:
|
||||
requires:
|
||||
- build
|
||||
- static-tests:
|
||||
requires:
|
||||
- build
|
||||
- test-publish:
|
||||
requires:
|
||||
- build
|
||||
- test-doc-generation:
|
||||
requires:
|
||||
- build
|
||||
- submit-coverage:
|
||||
requires:
|
||||
- test-rest
|
||||
- test-python
|
||||
- test-python
|
||||
- static-tests-python
|
||||
# skip python tox run for now, as we don't yet have multiple test environments to support.
|
||||
#- test-rest-python
|
||||
- test-0xjs:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts:
|
||||
requires:
|
||||
- build
|
||||
- test-sol-compiler:
|
||||
requires:
|
||||
- build
|
||||
- test-rest:
|
||||
requires:
|
||||
- build
|
||||
- prettier:
|
||||
requires:
|
||||
- build
|
||||
- lint:
|
||||
requires:
|
||||
- build
|
||||
- submit-coverage:
|
||||
requires:
|
||||
- test-0xjs
|
||||
- test-sol-compiler
|
||||
- test-rest
|
||||
- test-contracts
|
||||
|
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -1,7 +1 @@
|
||||
*.sol linguist-language=Solidity
|
||||
|
||||
# Automatically collapse generated files in GitHub.
|
||||
*.svg linguist-generated
|
||||
packages/contract-artifacts/artifacts/*json linguist-generated
|
||||
packages/abi-gen-wrappers/wrappers/*.ts liguist-generated
|
||||
|
||||
|
39
.github/autolabeler.yml
vendored
39
.github/autolabeler.yml
vendored
@@ -1,39 +0,0 @@
|
||||
python: ['python-packages']
|
||||
contracts: ['contracts']
|
||||
sol-doc: ['packages/sol-doc']
|
||||
sol-resolver: ['packages/sol-resolver']
|
||||
sra-spec: ['packages/sra-spec']
|
||||
subproviders: ['packages/subproviders']
|
||||
contract-addresses: ['packages/contract-addresses']
|
||||
migrations: ['packages/migrations']
|
||||
web3-wrapper: ['packages/web3-wrapper']
|
||||
sol-compiler: ['packages/sol-compiler']
|
||||
types: ['packages/types']
|
||||
instant: ['packages/instant']
|
||||
abi-gen-templates: ['packages/abi-gen-templates']
|
||||
abi-gen: ['packages/abi-gen']
|
||||
website: ['packages/website']
|
||||
sol-cov: ['packages/sol-cov']
|
||||
utils: ['packages/utils']
|
||||
tslint-config: ['packages/tslint-config']
|
||||
asset-buyer: ['packages/asset-buyer']
|
||||
order-watcher: ['packages/order-watcher']
|
||||
react-docs: ['packages/react-docs']
|
||||
order-utils: ['packages/order-utils']
|
||||
react-shared: ['packages/react-shared']
|
||||
assert: ['packages/assert']
|
||||
base-contract: ['packages/base-contract']
|
||||
typescript-typings: ['packages/typescript-typings']
|
||||
0x.js: ['packages/0x.js']
|
||||
abi-gen-wrappers: ['packages/abi-gen-wrappers']
|
||||
metacoin: ['packages/metacoin']
|
||||
contract-artifacts: ['packages/contract-artifacts']
|
||||
dev-utils: ['packages/dev-utils']
|
||||
contract-wrappers: ['packages/contract-wrappers']
|
||||
json-schemas: ['packages/json-schemas']
|
||||
ethereum-types: ['ethereum-types']
|
||||
connect: ['packages/connect']
|
||||
fill-scenarios: ['packages/fill-scenarios']
|
||||
dev-tools-pages: ['packages/dev-tools-pages']
|
||||
testnet-faucets: ['packages/testnet-faucets']
|
||||
monorepo-scripts: ['packages/monorepo-scripts']
|
19
.github/stale.yml
vendored
19
.github/stale.yml
vendored
@@ -1,19 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because no activity occured in 7 days after being marked as stale. If it's still relevant - feel free to reopen. Thank you
|
||||
for your contributions.
|
44
.gitignore
vendored
44
.gitignore
vendored
@@ -11,10 +11,6 @@ pids
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# SQLite database files
|
||||
*.db
|
||||
*.sqlite
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
@@ -45,7 +41,6 @@ typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
.npmrc
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
@@ -72,39 +67,26 @@ generated_docs/
|
||||
|
||||
TODO.md
|
||||
|
||||
# VSCode file
|
||||
.vscode
|
||||
|
||||
packages/website/public/bundle*
|
||||
packages/dev-tools-pages/public/bundle*
|
||||
packages/react-docs/example/public/bundle*
|
||||
|
||||
# server cli
|
||||
packages/testnet-faucets/server/
|
||||
|
||||
# generated contract artifacts/
|
||||
contracts/protocol/generated-artifacts/
|
||||
contracts/multisig/generated-artifacts/
|
||||
contracts/utils/generated-artifacts/
|
||||
contracts/libs/generated-artifacts/
|
||||
contracts/interfaces/generated-artifacts/
|
||||
contracts/tokens/generated-artifacts/
|
||||
contracts/examples/generated-artifacts/
|
||||
contracts/extensions/generated-artifacts/
|
||||
packages/sol-cov/test/fixtures/artifacts/
|
||||
packages/metacoin/artifacts/
|
||||
packages/order-watcher/test/artifacts/
|
||||
packages/contract-wrappers/test/artifacts/
|
||||
|
||||
# generated contract wrappers
|
||||
packages/abi-gen-wrappers/wrappers
|
||||
contracts/protocol/generated-wrappers/
|
||||
contracts/multisig/generated-wrappers/
|
||||
contracts/utils/generated-wrappers/
|
||||
contracts/libs/generated-wrappers/
|
||||
contracts/interfaces/generated-wrappers/
|
||||
contracts/tokens/generated-wrappers/
|
||||
contracts/examples/generated-wrappers/
|
||||
contracts/extensions/generated-wrappers/
|
||||
packages/0x.js/src/contract_wrappers/generated/
|
||||
packages/contracts/src/contract_wrappers/generated/
|
||||
packages/contract-wrappers/src/contract_wrappers/generated/
|
||||
packages/metacoin/src/contract_wrappers
|
||||
packages/fill-scenarios/src/generated_contract_wrappers/
|
||||
packages/order-watcher/src/generated_contract_wrappers/
|
||||
packages/migrations/src/contract_wrappers
|
||||
|
||||
# solc-bin in sol-compiler
|
||||
packages/sol-compiler/solc_bin/
|
||||
@@ -112,12 +94,4 @@ packages/sol-compiler/solc_bin/
|
||||
# Monorepo scripts
|
||||
packages/*/scripts/
|
||||
|
||||
# python stuff
|
||||
.eggs
|
||||
.mypy_cache
|
||||
.tox
|
||||
python-packages/*/build
|
||||
python-packages/*/dist
|
||||
__pycache__
|
||||
python-packages/*/src/*.egg-info
|
||||
python-packages/*/.coverage
|
||||
ganache.log
|
||||
|
@@ -1,29 +1,10 @@
|
||||
lib
|
||||
.nyc_output
|
||||
/contracts/protocol/generated-wrappers
|
||||
/contracts/protocol/generated-artifacts
|
||||
/contracts/multisig/generated-wrappers
|
||||
/contracts/multisig/generated-artifacts
|
||||
/contracts/utils/generated-wrappers
|
||||
/contracts/utils/generated-artifacts
|
||||
/contracts/libs/generated-wrappers
|
||||
/contracts/libs/generated-artifacts
|
||||
/contracts/interfaces/generated-wrappers
|
||||
/contracts/interfaces/generated-artifacts
|
||||
/contracts/tokens/generated-wrappers
|
||||
/contracts/tokens/generated-artifacts
|
||||
/contracts/examples/generated-wrappers
|
||||
/contracts/examples/generated-artifacts
|
||||
/contracts/extensions/generated-wrappers
|
||||
/contracts/extensions/generated-artifacts
|
||||
/packages/abi-gen-wrappers/src/generated-wrappers
|
||||
/packages/contract-artifacts/artifacts
|
||||
/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
|
||||
/packages/json-schemas/schemas
|
||||
/python-packages/order_utils/src/zero_ex/json_schemas/schemas
|
||||
/packages/metacoin/src/contract_wrappers
|
||||
/packages/0x.js/test/artifacts
|
||||
/packages/contracts/src/artifacts
|
||||
/packages/metacoin/artifacts
|
||||
/packages/sra-spec/public/
|
||||
/packages/contract-wrappers/test/artifacts
|
||||
/packages/order-watcher/test/artifacts
|
||||
/packages/migrations/artifacts/1.0.0
|
||||
package.json
|
||||
scripts/postpublish_utils.js
|
||||
packages/sol-cov/test/fixtures/artifacts
|
||||
|
35
CODEOWNERS
35
CODEOWNERS
@@ -1,35 +0,0 @@
|
||||
# See https://help.github.com/articles/about-codeowners/
|
||||
# for more info about CODEOWNERS file
|
||||
|
||||
# It uses the same pattern rule for gitignore file
|
||||
# https://git-scm.com/docs/gitignore#_pattern_format
|
||||
|
||||
# Website
|
||||
packages/asset-buyer/ @BMillman19 @fragosti @steveklebanoff
|
||||
packages/instant/ @BMillman19 @fragosti @steveklebanoff
|
||||
packages/website/ @BMillman19 @fragosti @fabioberger @steveklebanoff
|
||||
|
||||
# Dev tools & setup
|
||||
.circleci/ @LogvinovLeon
|
||||
packages/abi-gen/ @LogvinovLeon
|
||||
packages/base-contract/ @LogvinovLeon
|
||||
packages/connect/ @fragosti
|
||||
packages/abi-gen-templates/ @LogvinovLeon
|
||||
packages/contract-addresses/ @albrow
|
||||
packages/contract-artifacts/ @albrow
|
||||
packages/dev-utils/ @LogvinovLeon @fabioberger
|
||||
packages/devnet/ @albrow
|
||||
packages/ethereum-types/ @LogvinovLeon
|
||||
packages/metacoin/ @LogvinovLeon
|
||||
packages/monorepo-scripts/ @fabioberger
|
||||
packages/order-utils/ @fabioberger @LogvinovLeon
|
||||
packages/sol-compiler/ @LogvinovLeon
|
||||
packages/sol-cov/ @LogvinovLeon
|
||||
packages/sol-resolver/ @LogvinovLeon
|
||||
packages/subproviders/ @fabioberger @dekz
|
||||
packages/verdaccio/ @albrow
|
||||
packages/web3-wrapper/ @LogvinovLeon @fabioberger
|
||||
python-packages/ @feuGeneA
|
||||
|
||||
# Protocol/smart contracts
|
||||
contracts/core/test/ @albrow
|
@@ -1,92 +1,49 @@
|
||||
## 0x Contribution Guide
|
||||
|
||||
We welcome contributions from anyone on the internet and are grateful for even the smallest contributions. This document will help get you setup to start contributing back to 0x.
|
||||
Thank you for your interest in contributing to 0x protocol! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
|
||||
|
||||
### Getting started
|
||||
### How to contribute
|
||||
|
||||
1. Fork `0xproject/0x-monorepo`
|
||||
2. Clone your fork
|
||||
3. Follow the [installation & build steps](https://github.com/0xProject/0x-monorepo#install-dependencies) in the repo's top-level README.
|
||||
4. Setup the recommended [Development Tooling](#development-tooling).
|
||||
5. Open a PR with the `[WIP]` flag against the `development` branch and describe the change you are intending to undertake in the PR description. (see [our branch naming conventions](#branch-structure))
|
||||
If you'd like to contribute to 0x protocol, please fork the repo, fix, commit and send a pull request against the `development` branch for the maintainers to review and merge into the main code base. If you wish to submit more complex changes though, please check with a core dev first on [our RocketChat #dev channel](http://chat.0xproject.com) to ensure those changes are in-line with the general philosophy of the project and/or to get some early feedback which can make both your efforts easier as well as our review and merge procedures quick and simple.
|
||||
|
||||
Before removing the `[WIP]` tag and submitting the PR for review, make sure:
|
||||
We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other contributors know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the '[WIP]' prefix to the PR title. Please make sure your contributions adhere to our coding guidelines:
|
||||
|
||||
* It passes our linter checks (`yarn lint`)
|
||||
* It is properly formatted with Prettier (`yarn prettier`)
|
||||
* It passes our continuous integration tests (See: [Enabling code coverage checks on your fork](#enabling-code-coverage-checks-on-your-fork) for instructions on getting the `submit-coverage` test to pass on forks)
|
||||
* You've created/updated the corresponding [CHANGELOG](#CHANGELOGs) entries.
|
||||
* Your changes have sufficient test coverage (e.g regression tests have been added for bug fixes)
|
||||
* Pull requests adding features or refactoring should be opened against the `development` branch
|
||||
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
|
||||
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||
|
||||
### Branch structure
|
||||
### Code quality
|
||||
|
||||
We have two main branches:
|
||||
Because 0x.js is used by multiple relayers in production and their businesses depend on it, we strive for exceptional code quality. Please follow the existing code standards and conventions. `tslint` and `prettier` (described below) will help you.
|
||||
|
||||
* `master` represents the most recently released (published on npm) version of the codebase.
|
||||
* `development` represents the current development state of the codebase.
|
||||
If you're adding functionality, please also add tests and make sure they pass. We have an automatic coverage reporting tool, so we'll see it if they are missing ;)
|
||||
If you're adding a new public function/member, make sure you document it with Java doc-style comments. We use typedoc to generate [awesome documentation](https://0xproject.com/docs/0xjs) from the comments within our source code.
|
||||
|
||||
ALL PRs should be opened against `development`.
|
||||
If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add an entry in it for the change made to the package. For published packages, only changes that modify the public interface or behavior of the package need a CHANGELOG entry.
|
||||
|
||||
Branch names should be prefixed with `fix`, `feature` or `refactor`.
|
||||
### Styleguide
|
||||
|
||||
* e.g `fix/broken-wiki-link`
|
||||
* If the PR only edits a single package, add it's name too
|
||||
* e.g `fix/website/broken-wiki-link`
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code style consistent.
|
||||
|
||||
### CHANGELOGs
|
||||
To lint your code just run: `yarn lint`
|
||||
|
||||
At 0x we use [Semantic Versioning](http://semver.org/) for all our published packages. If a change you make corresponds to a semver bump, you must modify the package's `CHANGELOG.json` file accordingly.
|
||||
|
||||
Each CHANGELOG entry that corresponds to a published package will have a `timestamp`. If no entry exists without a `timestamp`, you must first create a new one:
|
||||
|
||||
```
|
||||
{
|
||||
"version": "1.0.1", <- The updated package version
|
||||
"changes": [
|
||||
{
|
||||
"note": "", <- Describe your change
|
||||
"PR": 100 <- Your PR number
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
If an entry without a `timestamp` already exists, this means other changes have been introduced by other collaborators since the last publish. Add your changes to the list of notes and adjust the version if your PR introduces a greater semver change (i.e current changes required a patch bump, but your changes require a major version bump).
|
||||
|
||||
### Development Tooling
|
||||
|
||||
We strongly recommend you use the [VSCode](https://code.visualstudio.com/) text editor since most of our code is written in Typescript and it offers amazing support for the language.
|
||||
|
||||
#### Linter
|
||||
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code-style consistent.
|
||||
|
||||
Use `yarn:lint` to lint the entire monorepo, and `PKG={PACKAGE_NAME} yarn lint` to lint a specific package.
|
||||
|
||||
If you want to change a rule, or add a custom rule, please make these changes to our [tslint-config](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) package. All other packages have it as a dependency.
|
||||
|
||||
Integrate it into your text editor:
|
||||
|
||||
* VSCode: [vscode-tslint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint)
|
||||
* Atom: [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
|
||||
#### Auto-formatter
|
||||
|
||||
We use [Prettier](https://prettier.io/) to auto-format our code. Be sure to either add a [text editor integration](https://prettier.io/docs/en/editors.html) or a [pre-commit hook](https://prettier.io/docs/en/precommit.html) to properly format your code changes.
|
||||
We also use [Prettier](https://prettier.io/) to auto-format our code. Be sure to either add a [text editor integration](https://prettier.io/docs/en/editors.html) or a [pre-commit hook](https://prettier.io/docs/en/precommit.html) to properly format your code changes.
|
||||
|
||||
If using the Atom text editor, we recommend you install the following packages:
|
||||
|
||||
* VSCode: [prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
* Atom: [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
||||
|
||||
## Fix `submit-coverage` CI failure
|
||||
Our CI will also run TSLint and Prettier as a part of the test run when you submit your PR. Make sure that the CI tests pass for your contribution.
|
||||
|
||||
If you simply fork the repo and then create a PR from it, your PR will fail the `submit-coverage` check on CI. This is because the 0x CircleCI configuration sets the `COVERALLS_REPO_TOKEN` environment variable to the token for `0xProject/0x-monorepo`, but when running the check against your fork the token needs to match your repo's name `your-username/0x-monorepo`.
|
||||
### Branch structure & versioning
|
||||
|
||||
To facilitate this check, after creating your fork, but before creating the branch for your PR, do the following:
|
||||
We use [semantic versioning](http://semver.org/), but before a package reaches v1.0.0 all breaking changes as well as new features will be minor version bumps.
|
||||
|
||||
1. Log in to [coveralls.io](https://coveralls.io/), go to `Add Repos`, and enable your fork. Then go to the settings for that repo, and copy the `Repo Token` identifier.
|
||||
2. Log in to [CircleCI](https://circleci.com/login), go to `Add Projects`, click the `Set Up Project` button corresponding to your fork, and then click `Start Building`. (Aside from step 3 below, no actual set up is needed, since it will use the `.circleci/config.yml` file in 0x-monorepo, so you can ignore all of the instruction/explanation given on the page with the `Start Building` button.)
|
||||
3. In CircleCI, configure your project to add an environment variable, with name `COVERALLS_REPO_TOKEN`, and for the value paste in the `Repo Token` you copied in step 1.
|
||||
We have two main branches: `master` and `development`.
|
||||
|
||||
Now, when you push to your branch, CircleCI will automatically run all of the checks in your own instance, and the coverage check will work since it has the proper `Repo Token`, and the PR will magically refer to your own checks rather than running them in the 0x CircleCI instance.
|
||||
`master` represents the most recent released (published on npm) version.
|
||||
|
||||
`development` represents the development state and is a default branch to which you will submit a PR. We use this structure so that we can push hotfixes to the currently released version without needing to publish all the changes made towards the next release. If a hotfix is implemented on `master`, it is back-ported to `development`.
|
||||
|
@@ -46,14 +46,10 @@
|
||||
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
|
||||
| Package | Version |
|
||||
| ------: | :------ |
|
||||
|
||||
|
||||
<!-- For example:
|
||||
| `0x.js` | 2.0.4 |
|
||||
| `Exchange Contract` | v2 |
|
||||
-->
|
||||
| Package | Version |
|
||||
| ------------------: | :------ |
|
||||
| `0x.js` | 0.25.0 |
|
||||
| `Exchange Contract` | v1 |
|
||||
|
||||
| Network |
|
||||
| ------- |
|
||||
|
4
LICENSE
4
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright 2017 ZeroEx Intl.
|
||||
Copyright 2017 ZeroEx Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -10,4 +10,4 @@ Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
limitations under the License.
|
@@ -1,26 +1,41 @@
|
||||
<!--- Thank you for taking the time to submit a Pull Request -->
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Description
|
||||
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Testing instructions
|
||||
## Motivation and Context
|
||||
|
||||
<!--- Please describe how reviewers can test your changes -->
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
## How Has This Been Tested?
|
||||
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
|
||||
## Types of changes
|
||||
|
||||
<!--- What types of changes does your code introduce? Uncomment all the bullets that apply: -->
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
|
||||
<!-- * Bug fix (non-breaking change which fixes an issue) -->
|
||||
|
||||
<!-- * New feature (non-breaking change which adds functionality) -->
|
||||
|
||||
<!-- * Breaking change (fix or feature that would cause existing functionality to change) -->
|
||||
* [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
* [ ] New feature (non-breaking change which adds functionality)
|
||||
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
## Checklist:
|
||||
|
||||
<!--- The following points should be used to indicate the progress of your PR. Put an `x` in all the boxes that apply right now, and come back over time and check them off as you make progress. If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
|
||||
* [ ] Prefix PR title with `[WIP]` if necessary.
|
||||
* [ ] Add tests to cover changes as needed.
|
||||
* [ ] Update documentation as needed.
|
||||
* [ ] Add new entries to the relevant CHANGELOG.jsons.
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
* [ ] Change requires a change to the documentation.
|
||||
* [ ] Added tests to cover my changes.
|
||||
* [ ] Added new entries to the relevant CHANGELOG.jsons.
|
||||
* [ ] Labeled this PR with the 'WIP' label if it is a work in progress.
|
||||
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
||||
|
124
README.md
124
README.md
@@ -2,15 +2,12 @@
|
||||
|
||||
---
|
||||
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. For more information on how it works, check out the [0x protocol specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. A full description of the protocol may be found in our [whitepaper][whitepaper-url].
|
||||
|
||||
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
|
||||
|
||||
If you're developing on 0x now or are interested in using 0x infrastructure in the future, please join our [developer mailing list][dev-mailing-list-url] for updates.
|
||||
|
||||
[website-url]: https://0xproject.com
|
||||
[website-url]: https://0xproject.com/
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
[dev-mailing-list-url]: http://eepurl.com/dx4cPf
|
||||
|
||||
[](https://circleci.com/gh/0xProject/0x-monorepo)
|
||||
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)
|
||||
@@ -18,81 +15,60 @@ If you're developing on 0x now or are interested in using 0x infrastructure in t
|
||||
[](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
## Packages
|
||||
### Published Packages
|
||||
|
||||
Visit our [developer portal](https://0xproject.com/docs/order-utils) for a comprehensive list of core & community maintained packages. All packages maintained with this monorepo are listed below.
|
||||
| Package | Version | Description |
|
||||
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
|
||||
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [](https://www.npmjs.com/package/@0xproject/sol-compiler) | A thin wrapper around Solc.js that outputs artifacts, resolves imports, only re-compiles when needed, and other niceties. |
|
||||
| [`@0xproject/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
|
||||
| [`@0xproject/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
|
||||
| [`@0xproject/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
|
||||
| [`@0xproject/sra-report`](/packages/sra-report) | [](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
|
||||
| [`@0xproject/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
|
||||
### Python Packages
|
||||
### Private Packages
|
||||
|
||||
| Package | Version | Description |
|
||||
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| [`0x-order-utils`](/python-packages/order_utils) | [](https://pypi.org/project/0x-order-utils/) | A set of utilities for generating, parsing, signing and validating 0x orders |
|
||||
| [`0x-sra-client`](/python-packages/sra_client) | [](https://pypi.org/project/0x-sra-client/) | A Python client for interacting with servers conforming to the Standard Relayer API specification |
|
||||
|
||||
### Typescript/Javascript Packages
|
||||
|
||||
#### 0x-specific packages
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | An aggregate package combining many smaller utility packages for interacting with the 0x protocol |
|
||||
| [`@0x/contract-addresses`](/packages/contract-addresses) | [](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network. |
|
||||
| [`@0x/contract-wrappers`](/packages/contract-wrappers) | [](https://www.npmjs.com/package/@0x/contract-wrappers) | JS/TS wrappers for interacting with the 0x smart contracts |
|
||||
| [`@0x/order-utils`](/packages/order-utils) | [](https://www.npmjs.com/package/@0x/order-utils) | A set of utilities for generating, parsing, signing and validating 0x orders |
|
||||
| [`@0x/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0x/json-schemas) | 0x-related JSON schemas |
|
||||
| [`@0x/order-watcher`](/packages/order-watcher) | [](https://www.npmjs.com/package/@0x/order-watcher) | An order watcher daemon that watches for order validity |
|
||||
| [`@0x/migrations`](/packages/migrations) | [](https://www.npmjs.com/package/@0x/migrations) | Migration tool for deploying 0x smart contracts on private testnets |
|
||||
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts |
|
||||
| [`@0x/abi-gen-wrappers`](/packages/abi-gen-wrappers) | [](https://www.npmjs.com/package/@0x/abi-gen-wrappers) | Low-level 0x smart contract wrappers generated using `@0x/abi-gen` |
|
||||
| [`@0x/sra-spec`](/packages/sra-spec) | [](https://www.npmjs.com/package/@0x/sra-spec) | OpenAPI specification for the Standard Relayer API |
|
||||
| [`@0x/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0x/connect) | An HTTP/WS client for interacting with the Standard Relayer API |
|
||||
| [`@0x/asset-buyer`](/packages/asset-buyer) | [](https://www.npmjs.com/package/@0x/asset-buyer) | Convenience package for discovering and buying assets with Ether |
|
||||
|
||||
#### Ethereum tooling
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`@0x/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0x/web3-wrapper) | An Ethereum JSON RPC client |
|
||||
| [`@0x/sol-compiler`](/packages/sol-compiler) | [](https://www.npmjs.com/package/@0x/sol-compiler) | A wrapper around solc-js that adds smart re-compilation, ability to compile an entire project, Solidity version specific compilation, standard input description support and much more. |
|
||||
| [`@0x/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0x/sol-cov) | A solidity test coverage tool |
|
||||
| [`@0x/sol-resolver`](/packages/sol-resolver) | [](https://www.npmjs.com/package/@0x/sol-resolver) | Import resolver for smart contracts dependencies |
|
||||
| [`@0x/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0x/subproviders) | Web3 provider middlewares (e.g. LedgerSubprovider) |
|
||||
| [`@0x/sol-doc`](/packages/sol-doc) | [](https://www.npmjs.com/package/@0x/sol-doc) | Solidity documentation generator |
|
||||
|
||||
#### Utilities
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| [`@0x/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0x/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0x/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0x/tslint-config) | Custom TSLint rules used by the 0x core team |
|
||||
| [`@0x/types`](/packages/types) | [](https://www.npmjs.com/package/@0x/types) | Shared type declarations |
|
||||
| [`@0x/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0x/typescript-typings) | Repository of types for external packages |
|
||||
| [`@0x/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0x/utils) | Shared utilities |
|
||||
| [`@0x/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0x/react-docs) | React documentation component for rendering TypeDoc & sol-doc generated JSON |
|
||||
| [`@0x/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0x/react-shared) | 0x shared react components |
|
||||
| [`@0x/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0x/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0x/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0x/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||
| [`@0x/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0x/dev-utils) | Dev utils to be shared across 0x packages |
|
||||
| [`@0x/fill-scenarios`](/packages/fill-scenarios) | [](https://www.npmjs.com/package/@0x/fill-scenarios) | 0x order fill scenario generator |
|
||||
|
||||
#### Private Packages
|
||||
|
||||
| Package | Description |
|
||||
| -------------------------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| [`@0x/contracts`](/contracts/core) | 0x protocol solidity smart contracts & tests |
|
||||
| [`@0x/instant`](/packages/instant) | A free and flexible way to offer simple crypto purchasing in any app or website. |
|
||||
| [`@0x/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0x/website`](/packages/website) | 0x website |
|
||||
| Package | Description |
|
||||
| --------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| [`@0xproject/contracts`](/packages/contracts) | 0x solidity smart contracts & tests |
|
||||
| [`@0xproject/react-docs-example`](/packages/react-docs-example) | Example documentation site created with `@0xproject/react-docs` |
|
||||
| [`@0xproject/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0xproject/website`](/packages/website) | 0x website & Portal DApp |
|
||||
|
||||
## Usage
|
||||
|
||||
Dedicated documentation pages:
|
||||
|
||||
* [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
* [0x Connect](https://0xproject.com/docs/connect)
|
||||
* [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
* [Subproviders](https://0xproject.com/docs/subproviders)
|
||||
* [Sol Compiler](https://0xproject.com/docs/sol-compiler)
|
||||
* [Web3-wrapper](https://0xproject.com/docs/web3-wrapper)
|
||||
* [JSON-schemas](https://0xproject.com/docs/json-schemas)
|
||||
* [Sol-cov](https://0xproject.com/docs/sol-cov)
|
||||
* [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
|
||||
Node version >= 6.12 is required.
|
||||
|
||||
Most of the packages require additional typings for external dependencies.
|
||||
You can include those by prepending the `@0x/typescript-typings` package to your [`typeRoots`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) config.
|
||||
You can include those by prepending @0xproject/typescript-typings package to your [`typeRoots`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) config.
|
||||
|
||||
```json
|
||||
"typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"],
|
||||
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
|
||||
```
|
||||
|
||||
## Contributing
|
||||
@@ -103,10 +79,10 @@ We strongly recommend that the community help us make improvements and determine
|
||||
|
||||
### Install dependencies
|
||||
|
||||
Make sure you are using Yarn v1.9.4. To install using brew:
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
brew install yarn@1.9.4
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
@@ -126,7 +102,7 @@ yarn build
|
||||
To build a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0x/web3-wrapper yarn build
|
||||
PKG=@0xproject/web3-wrapper yarn build
|
||||
```
|
||||
|
||||
### Watch
|
||||
@@ -143,7 +119,7 @@ To watch a specific package and all it's dependent packages:
|
||||
PKG=[NPM_PACKAGE_NAME] yarn watch
|
||||
|
||||
e.g
|
||||
PKG=@0x/web3-wrapper yarn watch
|
||||
PKG=@0xproject/web3-wrapper yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
@@ -199,5 +175,5 @@ yarn test
|
||||
Run a specific package's test:
|
||||
|
||||
```bash
|
||||
PKG=@0x/web3-wrapper yarn test
|
||||
PKG=@0xproject/web3-wrapper yarn test
|
||||
```
|
||||
|
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"extends": "default",
|
||||
"rules": {
|
||||
"avoid-low-level-calls": false,
|
||||
"avoid-tx-origin": "warn",
|
||||
"bracket-align": false,
|
||||
"code-complexity": false,
|
||||
"const-name-snakecase": "error",
|
||||
"expression-indent": "error",
|
||||
"function-max-lines": false,
|
||||
"func-order": "error",
|
||||
"indent": ["error", 4],
|
||||
"max-line-length": ["warn", 160],
|
||||
"no-inline-assembly": false,
|
||||
"quotes": ["error", "double"],
|
||||
"separate-by-one-line-in-contract": "error",
|
||||
"space-after-comma": "error",
|
||||
"statement-indent": "error"
|
||||
}
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
# Contracts testing options
|
||||
|
||||
## Revert stack traces
|
||||
|
||||
If you want to see helpful stack traces (incl. line number, code snippet) for smart contract reverts, run the tests with:
|
||||
|
||||
```
|
||||
yarn test:trace
|
||||
```
|
||||
|
||||
**Note:** This currently slows down the test runs and is therefore not enabled by default.
|
||||
|
||||
## Backing Ethereum node
|
||||
|
||||
By default, our tests run against an in-process [Ganache](https://github.com/trufflesuite/ganache-core) instance. In order to run the tests against [Geth](https://github.com/ethereum/go-ethereum), first follow the instructions in the README for the devnet package to start the devnet Geth node. Then run:
|
||||
|
||||
```bash
|
||||
TEST_PROVIDER=geth yarn test
|
||||
```
|
||||
|
||||
## Code coverage
|
||||
|
||||
In order to see the Solidity code coverage output generated by `@0x/sol-cov`, run:
|
||||
|
||||
```
|
||||
yarn test:coverage
|
||||
```
|
||||
|
||||
## Gas profiler
|
||||
|
||||
In order to profile the gas costs for a specific smart contract call/transaction, you can run the tests in `profiler` mode.
|
||||
|
||||
**Note:** Traces emitted by ganache have incorrect gas costs so we recommend using Geth for profiling.
|
||||
|
||||
```
|
||||
TEST_PROVIDER=geth yarn test:profiler
|
||||
```
|
||||
|
||||
You'll see a warning that you need to explicitly enable and disable the profiler before and after the block of code you want to profile.
|
||||
|
||||
```typescript
|
||||
import { profiler } from './utils/profiler';
|
||||
profiler.start();
|
||||
// Some call to a smart contract
|
||||
profiler.stop();
|
||||
```
|
||||
|
||||
Without explicitly starting and stopping the profiler, the profiler output will be too busy, and therefore unusable.
|
@@ -1,56 +0,0 @@
|
||||
## Contract examples
|
||||
|
||||
Example smart contracts that interact with 0x protocol.
|
||||
|
||||
## Usage
|
||||
|
||||
Contracts can be found in the [contracts](./contracts) directory.
|
||||
This package contains example implementations of contracts that interact with the protocol but are _not_ intended for use in production. Examples include [filter](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#filter-contracts) contracts, a [Wallet](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#wallet) contract, and a [Validator](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#validator) contract, among others.
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
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/contracts-examples yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-examples yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"compilerSettings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": ["ExchangeWrapper", "Validator", "Wallet", "Whitelist"]
|
||||
}
|
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
|
||||
|
||||
contract ExchangeWrapper {
|
||||
|
||||
// Exchange contract.
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
IExchange internal EXCHANGE;
|
||||
|
||||
constructor (address _exchange)
|
||||
public
|
||||
{
|
||||
EXCHANGE = IExchange(_exchange);
|
||||
}
|
||||
|
||||
/// @dev Cancels all orders created by sender with a salt less than or equal to the targetOrderEpoch
|
||||
/// and senderAddress equal to this contract.
|
||||
/// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled.
|
||||
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
|
||||
/// @param makerSignature Proof that maker wishes to call this function with given params.
|
||||
function cancelOrdersUpTo(
|
||||
uint256 targetOrderEpoch,
|
||||
uint256 salt,
|
||||
bytes makerSignature
|
||||
)
|
||||
external
|
||||
{
|
||||
address makerAddress = msg.sender;
|
||||
|
||||
// Encode arguments into byte array.
|
||||
bytes memory data = abi.encodeWithSelector(
|
||||
EXCHANGE.cancelOrdersUpTo.selector,
|
||||
targetOrderEpoch
|
||||
);
|
||||
|
||||
// Call `cancelOrdersUpTo` via `executeTransaction`.
|
||||
EXCHANGE.executeTransaction(
|
||||
salt,
|
||||
makerAddress,
|
||||
data,
|
||||
makerSignature
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Fills an order using `msg.sender` as the taker.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
|
||||
/// @param orderSignature Proof that order has been created by maker.
|
||||
/// @param takerSignature Proof that taker wishes to call this function with given params.
|
||||
function fillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint256 salt,
|
||||
bytes memory orderSignature,
|
||||
bytes memory takerSignature
|
||||
)
|
||||
public
|
||||
{
|
||||
address takerAddress = msg.sender;
|
||||
|
||||
// Encode arguments into byte array.
|
||||
bytes memory data = abi.encodeWithSelector(
|
||||
EXCHANGE.fillOrder.selector,
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
orderSignature
|
||||
);
|
||||
|
||||
// Call `fillOrder` via `executeTransaction`.
|
||||
EXCHANGE.executeTransaction(
|
||||
salt,
|
||||
takerAddress,
|
||||
data,
|
||||
takerSignature
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IValidator.sol";
|
||||
|
||||
|
||||
contract Validator is
|
||||
IValidator
|
||||
{
|
||||
|
||||
// The single valid signer for this wallet.
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
address internal VALID_SIGNER;
|
||||
|
||||
/// @dev constructs a new `Validator` with a single valid signer.
|
||||
/// @param validSigner The sole, valid signer.
|
||||
constructor (address validSigner) public {
|
||||
VALID_SIGNER = validSigner;
|
||||
}
|
||||
|
||||
/// @dev Verifies that a signature is valid. `signer` must match `VALID_SIGNER`.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param signerAddress Address that should have signed the given hash.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of signature.
|
||||
// solhint-disable no-unused-vars
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
address signerAddress,
|
||||
bytes signature
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isValid)
|
||||
{
|
||||
return (signerAddress == VALID_SIGNER);
|
||||
}
|
||||
// solhint-enable no-unused-vars
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
|
||||
|
||||
contract Wallet is
|
||||
IWallet
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
// The owner of this wallet.
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
address internal WALLET_OWNER;
|
||||
|
||||
/// @dev constructs a new `Wallet` with a single owner.
|
||||
/// @param walletOwner The owner of this wallet.
|
||||
constructor (address walletOwner) public {
|
||||
WALLET_OWNER = walletOwner;
|
||||
}
|
||||
|
||||
/// @dev Validates an EIP712 signature.
|
||||
/// The signer must match the owner of this wallet.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param eip712Signature Proof of signing.
|
||||
/// @return Validity of signature.
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
bytes eip712Signature
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isValid)
|
||||
{
|
||||
require(
|
||||
eip712Signature.length == 65,
|
||||
"LENGTH_65_REQUIRED"
|
||||
);
|
||||
|
||||
uint8 v = uint8(eip712Signature[0]);
|
||||
bytes32 r = eip712Signature.readBytes32(1);
|
||||
bytes32 s = eip712Signature.readBytes32(33);
|
||||
address recoveredAddress = ecrecover(hash, v, r, s);
|
||||
isValid = WALLET_OWNER == recoveredAddress;
|
||||
return isValid;
|
||||
}
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
|
||||
|
||||
|
||||
contract Whitelist is
|
||||
Ownable
|
||||
{
|
||||
|
||||
// Mapping of address => whitelist status.
|
||||
mapping (address => bool) public isWhitelisted;
|
||||
|
||||
// Exchange contract.
|
||||
// solhint-disable var-name-mixedcase
|
||||
IExchange internal EXCHANGE;
|
||||
bytes internal TX_ORIGIN_SIGNATURE;
|
||||
// solhint-enable var-name-mixedcase
|
||||
|
||||
byte constant internal VALIDATOR_SIGNATURE_BYTE = "\x05";
|
||||
|
||||
constructor (address _exchange)
|
||||
public
|
||||
{
|
||||
EXCHANGE = IExchange(_exchange);
|
||||
TX_ORIGIN_SIGNATURE = abi.encodePacked(address(this), VALIDATOR_SIGNATURE_BYTE);
|
||||
}
|
||||
|
||||
/// @dev Adds or removes an address from the whitelist.
|
||||
/// @param target Address to add or remove from whitelist.
|
||||
/// @param isApproved Whitelist status to assign to address.
|
||||
function updateWhitelistStatus(
|
||||
address target,
|
||||
bool isApproved
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
isWhitelisted[target] = isApproved;
|
||||
}
|
||||
|
||||
/// @dev Verifies signer is same as signer of current Ethereum transaction.
|
||||
/// NOTE: This function can currently be used to validate signatures coming from outside of this contract.
|
||||
/// Extra safety checks can be added for a production contract.
|
||||
/// @param signerAddress Address that should have signed the given hash.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of order signature.
|
||||
// solhint-disable no-unused-vars
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
address signerAddress,
|
||||
bytes signature
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isValid)
|
||||
{
|
||||
// solhint-disable-next-line avoid-tx-origin
|
||||
return signerAddress == tx.origin;
|
||||
}
|
||||
// solhint-enable no-unused-vars
|
||||
|
||||
/// @dev Fills an order using `msg.sender` as the taker.
|
||||
/// The transaction will revert if both the maker and taker are not whitelisted.
|
||||
/// Orders should specify this contract as the `senderAddress` in order to gaurantee
|
||||
/// that both maker and taker have been whitelisted.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
|
||||
/// @param orderSignature Proof that order has been created by maker.
|
||||
function fillOrderIfWhitelisted(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint256 salt,
|
||||
bytes memory orderSignature
|
||||
)
|
||||
public
|
||||
{
|
||||
address takerAddress = msg.sender;
|
||||
|
||||
// This contract must be the entry point for the transaction.
|
||||
require(
|
||||
// solhint-disable-next-line avoid-tx-origin
|
||||
takerAddress == tx.origin,
|
||||
"INVALID_SENDER"
|
||||
);
|
||||
|
||||
// Check if maker is on the whitelist.
|
||||
require(
|
||||
isWhitelisted[order.makerAddress],
|
||||
"MAKER_NOT_WHITELISTED"
|
||||
);
|
||||
|
||||
// Check if taker is on the whitelist.
|
||||
require(
|
||||
isWhitelisted[takerAddress],
|
||||
"TAKER_NOT_WHITELISTED"
|
||||
);
|
||||
|
||||
// Encode arguments into byte array.
|
||||
bytes memory data = abi.encodeWithSelector(
|
||||
EXCHANGE.fillOrder.selector,
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
orderSignature
|
||||
);
|
||||
|
||||
// Call `fillOrder` via `executeTransaction`.
|
||||
EXCHANGE.executeTransaction(
|
||||
salt,
|
||||
takerAddress,
|
||||
data,
|
||||
TX_ORIGIN_SIGNATURE
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0x/contracts-examples",
|
||||
"version": "1.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Smart contract examples of 0x protocol",
|
||||
"main": "lib/src/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"compile": "sol-compiler --contracts-dir contracts",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "generated-artifacts/@(ExchangeWrapper|Validator|Wallet|Whitelist).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/examples/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.19",
|
||||
"@0x/contracts-test-utils": "^1.0.2",
|
||||
"@0x/dev-utils": "^1.0.21",
|
||||
"@0x/sol-compiler": "^1.1.16",
|
||||
"@0x/sol-cov": "^2.1.16",
|
||||
"@0x/subproviders": "^2.1.8",
|
||||
"@0x/tslint-config": "^2.0.0",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.10",
|
||||
"@0x/contracts-interfaces": "^1.0.1",
|
||||
"@0x/contracts-libs": "^1.0.1",
|
||||
"@0x/contracts-multisig": "^1.0.1",
|
||||
"@0x/contracts-tokens": "^1.0.1",
|
||||
"@0x/contracts-utils": "^1.0.1",
|
||||
"@0x/order-utils": "^3.0.7",
|
||||
"@0x/types": "^1.4.1",
|
||||
"@0x/typescript-typings": "^3.0.6",
|
||||
"@0x/utils": "^2.0.8",
|
||||
"@0x/web3-wrapper": "^3.2.1",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^1.1.4",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as ExchangeWrapper from '../../generated-artifacts/ExchangeWrapper.json';
|
||||
import * as Validator from '../../generated-artifacts/Validator.json';
|
||||
import * as Wallet from '../../generated-artifacts/Wallet.json';
|
||||
import * as Whitelist from '../../generated-artifacts/Whitelist.json';
|
||||
|
||||
export const artifacts = {
|
||||
ExchangeWrapper: ExchangeWrapper as ContractArtifact,
|
||||
Validator: Validator as ContractArtifact,
|
||||
Wallet: Wallet as ContractArtifact,
|
||||
Whitelist: Whitelist as ContractArtifact,
|
||||
};
|
@@ -1,2 +0,0 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
@@ -1,4 +0,0 @@
|
||||
export * from '../../generated-wrappers/exchange_wrapper';
|
||||
export * from '../../generated-wrappers/validator';
|
||||
export * from '../../generated-wrappers/wallet';
|
||||
export * from '../../generated-wrappers/whitelist';
|
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"./generated-artifacts/ExchangeWrapper.json",
|
||||
"./generated-artifacts/Validator.json",
|
||||
"./generated-artifacts/Wallet.json",
|
||||
"./generated-artifacts/Whitelist.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
## Contract extensions
|
||||
|
||||
Smart contracts that implement extensions for the 0x protocol.
|
||||
|
||||
## Usage
|
||||
|
||||
Contract extensions of the protocol can be found in the [contracts](./contracts) directory. This directory contains contracts that interact with the 2.0.0 contracts and will be used in production, such as the [Forwarder](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract.
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
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/contracts-extensions yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-extensions yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"compilerSettings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": ["DutchAuction", "Forwarder"]
|
||||
}
|
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
|
||||
|
||||
|
||||
contract DutchAuction is
|
||||
SafeMath
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
// solhint-disable var-name-mixedcase
|
||||
IExchange internal EXCHANGE;
|
||||
|
||||
struct AuctionDetails {
|
||||
uint256 beginTimeSeconds; // Auction begin unix timestamp: sellOrder.makerAssetData
|
||||
uint256 endTimeSeconds; // Auction end unix timestamp: sellOrder.expiryTimeSeconds
|
||||
uint256 beginAmount; // Auction begin amount: sellOrder.makerAssetData
|
||||
uint256 endAmount; // Auction end amount: sellOrder.takerAssetAmount
|
||||
uint256 currentAmount; // Calculated amount given block.timestamp
|
||||
uint256 currentTimeSeconds; // block.timestamp
|
||||
}
|
||||
|
||||
constructor (address _exchange)
|
||||
public
|
||||
{
|
||||
EXCHANGE = IExchange(_exchange);
|
||||
}
|
||||
|
||||
/// @dev Matches the buy and sell orders at an amount given the following: the current block time, the auction
|
||||
/// start time and the auction begin amount. The sell order is a an order at the lowest amount
|
||||
/// at the end of the auction. Excess from the match is transferred to the seller.
|
||||
/// Over time the price moves from beginAmount to endAmount given the current block.timestamp.
|
||||
/// sellOrder.expiryTimeSeconds is the end time of the auction.
|
||||
/// sellOrder.takerAssetAmount is the end amount of the auction (lowest possible amount).
|
||||
/// sellOrder.makerAssetData is the ABI encoded Asset Proxy data with the following data appended
|
||||
/// buyOrder.makerAssetData is the buyers bid on the auction, must meet the amount for the current block timestamp
|
||||
/// (uint256 beginTimeSeconds, uint256 beginAmount).
|
||||
/// This function reverts in the following scenarios:
|
||||
/// * Auction has not started (auctionDetails.currentTimeSeconds < auctionDetails.beginTimeSeconds)
|
||||
/// * Auction has expired (auctionDetails.endTimeSeconds < auctionDetails.currentTimeSeconds)
|
||||
/// * Amount is invalid: Buy order amount is too low (buyOrder.makerAssetAmount < auctionDetails.currentAmount)
|
||||
/// * Amount is invalid: Invalid begin amount (auctionDetails.beginAmount > auctionDetails.endAmount)
|
||||
/// * Any failure in the 0x Match Orders
|
||||
/// @param buyOrder The Buyer's order. This order is for the current expected price of the auction.
|
||||
/// @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
|
||||
/// @param buySignature Proof that order was created by the buyer.
|
||||
/// @param sellSignature Proof that order was created by the seller.
|
||||
/// @return matchedFillResults amounts filled and fees paid by maker and taker of matched orders.
|
||||
function matchOrders(
|
||||
LibOrder.Order memory buyOrder,
|
||||
LibOrder.Order memory sellOrder,
|
||||
bytes memory buySignature,
|
||||
bytes memory sellSignature
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.MatchedFillResults memory matchedFillResults)
|
||||
{
|
||||
AuctionDetails memory auctionDetails = getAuctionDetails(sellOrder);
|
||||
// Ensure the auction has not yet started
|
||||
require(
|
||||
auctionDetails.currentTimeSeconds >= auctionDetails.beginTimeSeconds,
|
||||
"AUCTION_NOT_STARTED"
|
||||
);
|
||||
// Ensure the auction has not expired. This will fail later in 0x but we can save gas by failing early
|
||||
require(
|
||||
sellOrder.expirationTimeSeconds > auctionDetails.currentTimeSeconds,
|
||||
"AUCTION_EXPIRED"
|
||||
);
|
||||
// Validate the buyer amount is greater than the current auction amount
|
||||
require(
|
||||
buyOrder.makerAssetAmount >= auctionDetails.currentAmount,
|
||||
"INVALID_AMOUNT"
|
||||
);
|
||||
// Match orders, maximally filling `buyOrder`
|
||||
matchedFillResults = EXCHANGE.matchOrders(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buySignature,
|
||||
sellSignature
|
||||
);
|
||||
// The difference in sellOrder.takerAssetAmount and current amount is given as spread to the matcher
|
||||
// This may include additional spread from the buyOrder.makerAssetAmount and the currentAmount.
|
||||
// e.g currentAmount is 30, sellOrder.takerAssetAmount is 10 and buyOrder.makerAssetamount is 40.
|
||||
// 10 (40-30) is returned to the buyer, 20 (30-10) sent to the seller and 10 has previously
|
||||
// been transferred to the seller during matchOrders
|
||||
uint256 leftMakerAssetSpreadAmount = matchedFillResults.leftMakerAssetSpreadAmount;
|
||||
if (leftMakerAssetSpreadAmount > 0) {
|
||||
// ERC20 Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 1 * 32 | function parameters: |
|
||||
// | | 4 | 12 | 1. token address padding |
|
||||
// | | 16 | 20 | 2. token address |
|
||||
bytes memory assetData = sellOrder.takerAssetData;
|
||||
address token = assetData.readAddress(16);
|
||||
// Calculate the excess from the buy order. This can occur if the buyer sends in a higher
|
||||
// amount than the calculated current amount
|
||||
uint256 buyerExcessAmount = safeSub(buyOrder.makerAssetAmount, auctionDetails.currentAmount);
|
||||
uint256 sellerExcessAmount = safeSub(leftMakerAssetSpreadAmount, buyerExcessAmount);
|
||||
// Return the difference between auctionDetails.currentAmount and sellOrder.takerAssetAmount
|
||||
// to the seller
|
||||
if (sellerExcessAmount > 0) {
|
||||
IERC20Token(token).transfer(sellOrder.makerAddress, sellerExcessAmount);
|
||||
}
|
||||
// Return the difference between buyOrder.makerAssetAmount and auctionDetails.currentAmount
|
||||
// to the buyer
|
||||
if (buyerExcessAmount > 0) {
|
||||
IERC20Token(token).transfer(buyOrder.makerAddress, buyerExcessAmount);
|
||||
}
|
||||
}
|
||||
return matchedFillResults;
|
||||
}
|
||||
|
||||
/// @dev Calculates the Auction Details for the given order
|
||||
/// @param order The sell order
|
||||
/// @return AuctionDetails
|
||||
function getAuctionDetails(
|
||||
LibOrder.Order memory order
|
||||
)
|
||||
public
|
||||
returns (AuctionDetails memory auctionDetails)
|
||||
{
|
||||
uint256 makerAssetDataLength = order.makerAssetData.length;
|
||||
// It is unknown the encoded data of makerAssetData, we assume the last 64 bytes
|
||||
// are the Auction Details encoding.
|
||||
// Auction Details is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Params | | 2 * 32 | parameters: |
|
||||
// | | -64 | 32 | 1. auction begin unix timestamp |
|
||||
// | | -32 | 32 | 2. auction begin begin amount |
|
||||
// ERC20 asset data length is 4+32, 64 for auction details results in min length 100
|
||||
require(
|
||||
makerAssetDataLength >= 100,
|
||||
"INVALID_ASSET_DATA"
|
||||
);
|
||||
uint256 auctionBeginTimeSeconds = order.makerAssetData.readUint256(makerAssetDataLength - 64);
|
||||
uint256 auctionBeginAmount = order.makerAssetData.readUint256(makerAssetDataLength - 32);
|
||||
// Ensure the auction has a valid begin time
|
||||
require(
|
||||
order.expirationTimeSeconds > auctionBeginTimeSeconds,
|
||||
"INVALID_BEGIN_TIME"
|
||||
);
|
||||
uint256 auctionDurationSeconds = order.expirationTimeSeconds-auctionBeginTimeSeconds;
|
||||
// Ensure the auction goes from high to low
|
||||
uint256 minAmount = order.takerAssetAmount;
|
||||
require(
|
||||
auctionBeginAmount > minAmount,
|
||||
"INVALID_AMOUNT"
|
||||
);
|
||||
uint256 amountDelta = auctionBeginAmount-minAmount;
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
uint256 timestamp = block.timestamp;
|
||||
auctionDetails.beginTimeSeconds = auctionBeginTimeSeconds;
|
||||
auctionDetails.endTimeSeconds = order.expirationTimeSeconds;
|
||||
auctionDetails.beginAmount = auctionBeginAmount;
|
||||
auctionDetails.endAmount = minAmount;
|
||||
auctionDetails.currentTimeSeconds = timestamp;
|
||||
|
||||
uint256 remainingDurationSeconds = order.expirationTimeSeconds-timestamp;
|
||||
if (timestamp < auctionBeginTimeSeconds) {
|
||||
// If the auction has not yet begun the current amount is the auctionBeginAmount
|
||||
auctionDetails.currentAmount = auctionBeginAmount;
|
||||
} else if (timestamp >= order.expirationTimeSeconds) {
|
||||
// If the auction has ended the current amount is the minAmount.
|
||||
// Auction end time is guaranteed by 0x Exchange due to the order expiration
|
||||
auctionDetails.currentAmount = minAmount;
|
||||
} else {
|
||||
auctionDetails.currentAmount = safeAdd(
|
||||
minAmount,
|
||||
safeDiv(
|
||||
safeMul(remainingDurationSeconds, amountDelta),
|
||||
auctionDurationSeconds
|
||||
)
|
||||
);
|
||||
}
|
||||
return auctionDetails;
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./MixinWeth.sol";
|
||||
import "./MixinForwarderCore.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./MixinAssets.sol";
|
||||
import "./MixinExchangeWrapper.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract Forwarder is
|
||||
LibConstants,
|
||||
MixinWeth,
|
||||
MixinAssets,
|
||||
MixinExchangeWrapper,
|
||||
MixinForwarderCore
|
||||
{
|
||||
constructor (
|
||||
address _exchange,
|
||||
bytes memory _zrxAssetData,
|
||||
bytes memory _wethAssetData
|
||||
)
|
||||
public
|
||||
LibConstants(
|
||||
_exchange,
|
||||
_zrxAssetData,
|
||||
_wethAssetData
|
||||
)
|
||||
MixinForwarderCore()
|
||||
{}
|
||||
}
|
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
|
||||
import "@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol";
|
||||
import "@0x/contracts-tokens/contracts/tokens/ERC721Token/IERC721Token.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MAssets.sol";
|
||||
|
||||
|
||||
contract MixinAssets is
|
||||
Ownable,
|
||||
LibConstants,
|
||||
MAssets
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
|
||||
|
||||
/// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to
|
||||
/// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be
|
||||
/// used to withdraw assets that were accidentally sent to this contract.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of ERC20 token to withdraw.
|
||||
function withdrawAsset(
|
||||
bytes assetData,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
transferAssetToSender(assetData, amount);
|
||||
}
|
||||
|
||||
/// @dev Transfers given amount of asset to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferAssetToSender(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes4 proxyId = assetData.readBytes4(0);
|
||||
|
||||
if (proxyId == ERC20_DATA_ID) {
|
||||
transferERC20Token(assetData, amount);
|
||||
} else if (proxyId == ERC721_DATA_ID) {
|
||||
transferERC721Token(assetData, amount);
|
||||
} else {
|
||||
revert("UNSUPPORTED_ASSET_PROXY");
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Decodes ERC20 assetData and transfers given amount to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferERC20Token(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
address token = assetData.readAddress(16);
|
||||
|
||||
// Transfer tokens.
|
||||
// We do a raw call so we can check the success separate
|
||||
// from the return data.
|
||||
bool success = token.call(abi.encodeWithSelector(
|
||||
ERC20_TRANSFER_SELECTOR,
|
||||
msg.sender,
|
||||
amount
|
||||
));
|
||||
require(
|
||||
success,
|
||||
"TRANSFER_FAILED"
|
||||
);
|
||||
|
||||
// Check return data.
|
||||
// If there is no return data, we assume the token incorrectly
|
||||
// does not return a bool. In this case we expect it to revert
|
||||
// on failure, which was handled above.
|
||||
// If the token does return data, we require that it is a single
|
||||
// value that evaluates to true.
|
||||
assembly {
|
||||
if returndatasize {
|
||||
success := 0
|
||||
if eq(returndatasize, 32) {
|
||||
// First 64 bytes of memory are reserved scratch space
|
||||
returndatacopy(0, 0, 32)
|
||||
success := mload(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
require(
|
||||
success,
|
||||
"TRANSFER_FAILED"
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Decodes ERC721 assetData and transfers given amount to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferERC721Token(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
require(
|
||||
amount == 1,
|
||||
"INVALID_AMOUNT"
|
||||
);
|
||||
// Decode asset data.
|
||||
address token = assetData.readAddress(16);
|
||||
uint256 tokenId = assetData.readUint256(36);
|
||||
|
||||
// Perform transfer.
|
||||
IERC721Token(token).transferFrom(
|
||||
address(this),
|
||||
msg.sender,
|
||||
tokenId
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MExchangeWrapper.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibAbiEncoder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
|
||||
|
||||
contract MixinExchangeWrapper is
|
||||
LibAbiEncoder,
|
||||
LibFillResults,
|
||||
LibMath,
|
||||
LibConstants,
|
||||
MExchangeWrapper
|
||||
{
|
||||
/// @dev Fills the input order.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrderNoThrow(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
internal
|
||||
returns (FillResults memory fillResults)
|
||||
{
|
||||
// ABI encode calldata for `fillOrder`
|
||||
bytes memory fillOrderCalldata = abiEncodeFillOrder(
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
signature
|
||||
);
|
||||
|
||||
address exchange = address(EXCHANGE);
|
||||
|
||||
// Call `fillOrder` and handle any exceptions gracefully
|
||||
assembly {
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
exchange, // call address of Exchange contract
|
||||
0, // transfer 0 wei
|
||||
add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)
|
||||
mload(fillOrderCalldata), // length of input
|
||||
fillOrderCalldata, // write output over input
|
||||
128 // output size is 128 bytes
|
||||
)
|
||||
if success {
|
||||
mstore(fillResults, mload(fillOrderCalldata))
|
||||
mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))
|
||||
mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))
|
||||
mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))
|
||||
}
|
||||
}
|
||||
// fillResults values will be 0 by default if call was unsuccessful
|
||||
return fillResults;
|
||||
}
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of WETH has been sold by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param wethSellAmount Desired amount of WETH to sell.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 wethSellAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (FillResults memory totalFillResults)
|
||||
{
|
||||
bytes memory makerAssetData = orders[0].makerAssetData;
|
||||
bytes memory wethAssetData = WETH_ASSET_DATA;
|
||||
|
||||
uint256 ordersLength = orders.length;
|
||||
for (uint256 i = 0; i != ordersLength; i++) {
|
||||
|
||||
// We assume that asset being bought by taker is the same for each order.
|
||||
// We assume that asset being sold by taker is WETH for each order.
|
||||
orders[i].makerAssetData = makerAssetData;
|
||||
orders[i].takerAssetData = wethAssetData;
|
||||
|
||||
// Calculate the remaining amount of WETH to sell
|
||||
uint256 remainingTakerAssetFillAmount = safeSub(wethSellAmount, totalFillResults.takerAssetFilledAmount);
|
||||
|
||||
// Attempt to sell the remaining amount of WETH
|
||||
FillResults memory singleFillResults = fillOrderNoThrow(
|
||||
orders[i],
|
||||
remainingTakerAssetFillAmount,
|
||||
signatures[i]
|
||||
);
|
||||
|
||||
// Update amounts filled and fees paid by maker and taker
|
||||
addFillResults(totalFillResults, singleFillResults);
|
||||
|
||||
// Stop execution if the entire amount of takerAsset has been sold
|
||||
if (totalFillResults.takerAssetFilledAmount >= wethSellAmount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return totalFillResults;
|
||||
}
|
||||
|
||||
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// The asset being sold by taker must always be WETH.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyExactAmountWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (FillResults memory totalFillResults)
|
||||
{
|
||||
bytes memory makerAssetData = orders[0].makerAssetData;
|
||||
bytes memory wethAssetData = WETH_ASSET_DATA;
|
||||
|
||||
uint256 ordersLength = orders.length;
|
||||
for (uint256 i = 0; i != ordersLength; i++) {
|
||||
|
||||
// We assume that asset being bought by taker is the same for each order.
|
||||
// We assume that asset being sold by taker is WETH for each order.
|
||||
orders[i].makerAssetData = makerAssetData;
|
||||
orders[i].takerAssetData = wethAssetData;
|
||||
|
||||
// Calculate the remaining amount of makerAsset to buy
|
||||
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
|
||||
|
||||
// Convert the remaining amount of makerAsset to buy into remaining amount
|
||||
// of takerAsset to sell, assuming entire amount can be sold in the current order.
|
||||
// We round up because the exchange rate computed by fillOrder rounds in favor
|
||||
// of the Maker. In this case we want to overestimate the amount of takerAsset.
|
||||
uint256 remainingTakerAssetFillAmount = getPartialAmountCeil(
|
||||
orders[i].takerAssetAmount,
|
||||
orders[i].makerAssetAmount,
|
||||
remainingMakerAssetFillAmount
|
||||
);
|
||||
|
||||
// Attempt to sell the remaining amount of takerAsset
|
||||
FillResults memory singleFillResults = fillOrderNoThrow(
|
||||
orders[i],
|
||||
remainingTakerAssetFillAmount,
|
||||
signatures[i]
|
||||
);
|
||||
|
||||
// Update amounts filled and fees paid by maker and taker
|
||||
addFillResults(totalFillResults, singleFillResults);
|
||||
|
||||
// Stop execution if the entire amount of makerAsset has been bought
|
||||
uint256 makerAssetFilledAmount = totalFillResults.makerAssetFilledAmount;
|
||||
if (makerAssetFilledAmount >= makerAssetFillAmount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
require(
|
||||
makerAssetFilledAmount >= makerAssetFillAmount,
|
||||
"COMPLETE_FILL_FAILED"
|
||||
);
|
||||
return totalFillResults;
|
||||
}
|
||||
|
||||
/// @dev Buys zrxBuyAmount of ZRX fee tokens, taking into account ZRX fees for each order. This will guarantee
|
||||
/// that at least zrxBuyAmount of ZRX is purchased (sometimes slightly over due to rounding issues).
|
||||
/// It is possible that a request to buy 200 ZRX will require purchasing 202 ZRX
|
||||
/// as 2 ZRX is required to purchase the 200 ZRX fee tokens. This guarantees at least 200 ZRX for future purchases.
|
||||
/// The asset being sold by taker must always be WETH.
|
||||
/// @param orders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset.
|
||||
/// @param zrxBuyAmount Desired amount of ZRX to buy.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return totalFillResults Amounts filled and fees paid by maker and taker.
|
||||
function marketBuyExactZrxWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 zrxBuyAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (FillResults memory totalFillResults)
|
||||
{
|
||||
// Do nothing if zrxBuyAmount == 0
|
||||
if (zrxBuyAmount == 0) {
|
||||
return totalFillResults;
|
||||
}
|
||||
|
||||
bytes memory zrxAssetData = ZRX_ASSET_DATA;
|
||||
bytes memory wethAssetData = WETH_ASSET_DATA;
|
||||
uint256 zrxPurchased = 0;
|
||||
|
||||
uint256 ordersLength = orders.length;
|
||||
for (uint256 i = 0; i != ordersLength; i++) {
|
||||
|
||||
// All of these are ZRX/WETH, so we can drop the respective assetData from calldata.
|
||||
orders[i].makerAssetData = zrxAssetData;
|
||||
orders[i].takerAssetData = wethAssetData;
|
||||
|
||||
// Calculate the remaining amount of ZRX to buy.
|
||||
uint256 remainingZrxBuyAmount = safeSub(zrxBuyAmount, zrxPurchased);
|
||||
|
||||
// Convert the remaining amount of ZRX to buy into remaining amount
|
||||
// of WETH to sell, assuming entire amount can be sold in the current order.
|
||||
// We round up because the exchange rate computed by fillOrder rounds in favor
|
||||
// of the Maker. In this case we want to overestimate the amount of takerAsset.
|
||||
uint256 remainingWethSellAmount = getPartialAmountCeil(
|
||||
orders[i].takerAssetAmount,
|
||||
safeSub(orders[i].makerAssetAmount, orders[i].takerFee), // our exchange rate after fees
|
||||
remainingZrxBuyAmount
|
||||
);
|
||||
|
||||
// Attempt to sell the remaining amount of WETH.
|
||||
FillResults memory singleFillResult = fillOrderNoThrow(
|
||||
orders[i],
|
||||
remainingWethSellAmount,
|
||||
signatures[i]
|
||||
);
|
||||
|
||||
// Update amounts filled and fees paid by maker and taker.
|
||||
addFillResults(totalFillResults, singleFillResult);
|
||||
zrxPurchased = safeSub(totalFillResults.makerAssetFilledAmount, totalFillResults.takerFeePaid);
|
||||
|
||||
// Stop execution if the entire amount of ZRX has been bought.
|
||||
if (zrxPurchased >= zrxBuyAmount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
require(
|
||||
zrxPurchased >= zrxBuyAmount,
|
||||
"COMPLETE_FILL_FAILED"
|
||||
);
|
||||
return totalFillResults;
|
||||
}
|
||||
}
|
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MWeth.sol";
|
||||
import "./mixins/MAssets.sol";
|
||||
import "./mixins/MExchangeWrapper.sol";
|
||||
import "./interfaces/IForwarderCore.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
|
||||
|
||||
contract MixinForwarderCore is
|
||||
LibFillResults,
|
||||
LibMath,
|
||||
LibConstants,
|
||||
MWeth,
|
||||
MAssets,
|
||||
MExchangeWrapper,
|
||||
IForwarderCore
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
/// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf.
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID);
|
||||
require(
|
||||
proxyAddress != address(0),
|
||||
"UNREGISTERED_ASSET_PROXY"
|
||||
);
|
||||
ETHER_TOKEN.approve(proxyAddress, MAX_UINT);
|
||||
ZRX_TOKEN.approve(proxyAddress, MAX_UINT);
|
||||
}
|
||||
|
||||
/// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.
|
||||
/// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.
|
||||
/// 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).
|
||||
/// Any ETH not spent will be refunded to sender.
|
||||
/// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.
|
||||
/// @param feeSignatures Proofs that feeOrders have been created by makers.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
/// @return Amounts filled and fees paid by maker and taker for both sets of orders.
|
||||
function marketSellOrdersWithEth(
|
||||
LibOrder.Order[] memory orders,
|
||||
bytes[] memory signatures,
|
||||
LibOrder.Order[] memory feeOrders,
|
||||
bytes[] memory feeSignatures,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
public
|
||||
payable
|
||||
returns (
|
||||
FillResults memory orderFillResults,
|
||||
FillResults memory feeOrderFillResults
|
||||
)
|
||||
{
|
||||
// Convert ETH to WETH.
|
||||
convertEthToWeth();
|
||||
|
||||
uint256 wethSellAmount;
|
||||
uint256 zrxBuyAmount;
|
||||
uint256 makerAssetAmountPurchased;
|
||||
if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {
|
||||
// Calculate amount of WETH that won't be spent on ETH fees.
|
||||
wethSellAmount = getPartialAmountFloor(
|
||||
PERCENTAGE_DENOMINATOR,
|
||||
safeAdd(PERCENTAGE_DENOMINATOR, feePercentage),
|
||||
msg.value
|
||||
);
|
||||
// Market sell available WETH.
|
||||
// ZRX fees are paid with this contract's balance.
|
||||
orderFillResults = marketSellWeth(
|
||||
orders,
|
||||
wethSellAmount,
|
||||
signatures
|
||||
);
|
||||
// The fee amount must be deducted from the amount transfered back to sender.
|
||||
makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);
|
||||
} else {
|
||||
// 5% of WETH is reserved for filling feeOrders and paying feeRecipient.
|
||||
wethSellAmount = getPartialAmountFloor(
|
||||
MAX_WETH_FILL_PERCENTAGE,
|
||||
PERCENTAGE_DENOMINATOR,
|
||||
msg.value
|
||||
);
|
||||
// Market sell 95% of WETH.
|
||||
// ZRX fees are payed with this contract's balance.
|
||||
orderFillResults = marketSellWeth(
|
||||
orders,
|
||||
wethSellAmount,
|
||||
signatures
|
||||
);
|
||||
// Buy back all ZRX spent on fees.
|
||||
zrxBuyAmount = orderFillResults.takerFeePaid;
|
||||
feeOrderFillResults = marketBuyExactZrxWithWeth(
|
||||
feeOrders,
|
||||
zrxBuyAmount,
|
||||
feeSignatures
|
||||
);
|
||||
makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;
|
||||
}
|
||||
|
||||
// Transfer feePercentage of total ETH spent on primary orders to feeRecipient.
|
||||
// Refund remaining ETH to msg.sender.
|
||||
transferEthFeeAndRefund(
|
||||
orderFillResults.takerAssetFilledAmount,
|
||||
feeOrderFillResults.takerAssetFilledAmount,
|
||||
feePercentage,
|
||||
feeRecipient
|
||||
);
|
||||
|
||||
// Transfer purchased assets to msg.sender.
|
||||
transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
}
|
||||
|
||||
/// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.
|
||||
/// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.
|
||||
/// Any ETH not spent will be refunded to sender.
|
||||
/// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to purchase.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.
|
||||
/// @param feeSignatures Proofs that feeOrders have been created by makers.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
/// @return Amounts filled and fees paid by maker and taker for both sets of orders.
|
||||
function marketBuyOrdersWithEth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures,
|
||||
LibOrder.Order[] memory feeOrders,
|
||||
bytes[] memory feeSignatures,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
public
|
||||
payable
|
||||
returns (
|
||||
FillResults memory orderFillResults,
|
||||
FillResults memory feeOrderFillResults
|
||||
)
|
||||
{
|
||||
// Convert ETH to WETH.
|
||||
convertEthToWeth();
|
||||
|
||||
uint256 zrxBuyAmount;
|
||||
uint256 makerAssetAmountPurchased;
|
||||
if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {
|
||||
// If the makerAsset is ZRX, it is not necessary to pay fees out of this
|
||||
// contracts's ZRX balance because fees are factored into the price of the order.
|
||||
orderFillResults = marketBuyExactZrxWithWeth(
|
||||
orders,
|
||||
makerAssetFillAmount,
|
||||
signatures
|
||||
);
|
||||
// The fee amount must be deducted from the amount transfered back to sender.
|
||||
makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);
|
||||
} else {
|
||||
// Attemp to purchase desired amount of makerAsset.
|
||||
// ZRX fees are payed with this contract's balance.
|
||||
orderFillResults = marketBuyExactAmountWithWeth(
|
||||
orders,
|
||||
makerAssetFillAmount,
|
||||
signatures
|
||||
);
|
||||
// Buy back all ZRX spent on fees.
|
||||
zrxBuyAmount = orderFillResults.takerFeePaid;
|
||||
feeOrderFillResults = marketBuyExactZrxWithWeth(
|
||||
feeOrders,
|
||||
zrxBuyAmount,
|
||||
feeSignatures
|
||||
);
|
||||
makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;
|
||||
}
|
||||
|
||||
// Transfer feePercentage of total ETH spent on primary orders to feeRecipient.
|
||||
// Refund remaining ETH to msg.sender.
|
||||
transferEthFeeAndRefund(
|
||||
orderFillResults.takerAssetFilledAmount,
|
||||
feeOrderFillResults.takerAssetFilledAmount,
|
||||
feePercentage,
|
||||
feeRecipient
|
||||
);
|
||||
|
||||
// Transfer purchased assets to msg.sender.
|
||||
transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);
|
||||
}
|
||||
}
|
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MWeth.sol";
|
||||
|
||||
|
||||
contract MixinWeth is
|
||||
LibMath,
|
||||
LibConstants,
|
||||
MWeth
|
||||
{
|
||||
/// @dev Default payabale function, this allows us to withdraw WETH
|
||||
function ()
|
||||
public
|
||||
payable
|
||||
{
|
||||
require(
|
||||
msg.sender == address(ETHER_TOKEN),
|
||||
"DEFAULT_FUNCTION_WETH_CONTRACT_ONLY"
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Converts message call's ETH value into WETH.
|
||||
function convertEthToWeth()
|
||||
internal
|
||||
{
|
||||
require(
|
||||
msg.value > 0,
|
||||
"INVALID_MSG_VALUE"
|
||||
);
|
||||
ETHER_TOKEN.deposit.value(msg.value)();
|
||||
}
|
||||
|
||||
/// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.
|
||||
/// Refunds any excess ETH to msg.sender.
|
||||
/// @param wethSoldExcludingFeeOrders Amount of WETH sold when filling primary orders.
|
||||
/// @param wethSoldForZrx Amount of WETH sold when purchasing ZRX required for primary order fees.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
function transferEthFeeAndRefund(
|
||||
uint256 wethSoldExcludingFeeOrders,
|
||||
uint256 wethSoldForZrx,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
internal
|
||||
{
|
||||
// Ensure feePercentage is less than 5%.
|
||||
require(
|
||||
feePercentage <= MAX_FEE_PERCENTAGE,
|
||||
"FEE_PERCENTAGE_TOO_LARGE"
|
||||
);
|
||||
|
||||
// Ensure that no extra WETH owned by this contract has been sold.
|
||||
uint256 wethSold = safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx);
|
||||
require(
|
||||
wethSold <= msg.value,
|
||||
"OVERSOLD_WETH"
|
||||
);
|
||||
|
||||
// Calculate amount of WETH that hasn't been sold.
|
||||
uint256 wethRemaining = safeSub(msg.value, wethSold);
|
||||
|
||||
// Calculate ETH fee to pay to feeRecipient.
|
||||
uint256 ethFee = getPartialAmountFloor(
|
||||
feePercentage,
|
||||
PERCENTAGE_DENOMINATOR,
|
||||
wethSoldExcludingFeeOrders
|
||||
);
|
||||
|
||||
// Ensure fee is less than amount of WETH remaining.
|
||||
require(
|
||||
ethFee <= wethRemaining,
|
||||
"INSUFFICIENT_ETH_REMAINING"
|
||||
);
|
||||
|
||||
// Do nothing if no WETH remaining
|
||||
if (wethRemaining > 0) {
|
||||
// Convert remaining WETH to ETH
|
||||
ETHER_TOKEN.withdraw(wethRemaining);
|
||||
|
||||
// Pay ETH to feeRecipient
|
||||
if (ethFee > 0) {
|
||||
feeRecipient.transfer(ethFee);
|
||||
}
|
||||
|
||||
// Refund remaining ETH to msg.sender.
|
||||
uint256 ethRefund = safeSub(wethRemaining, ethFee);
|
||||
if (ethRefund > 0) {
|
||||
msg.sender.transfer(ethRefund);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract IAssets {
|
||||
|
||||
/// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to
|
||||
/// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be
|
||||
/// used to withdraw assets that were accidentally sent to this contract.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of ERC20 token to withdraw.
|
||||
function withdrawAsset(
|
||||
bytes assetData,
|
||||
uint256 amount
|
||||
)
|
||||
external;
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./IForwarderCore.sol";
|
||||
import "./IAssets.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract IForwarder is
|
||||
IForwarderCore,
|
||||
IAssets
|
||||
{}
|
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IForwarderCore {
|
||||
|
||||
/// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.
|
||||
/// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.
|
||||
/// 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).
|
||||
/// Any ETH not spent will be refunded to sender.
|
||||
/// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.
|
||||
/// @param feeSignatures Proofs that feeOrders have been created by makers.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
/// @return Amounts filled and fees paid by maker and taker for both sets of orders.
|
||||
function marketSellOrdersWithEth(
|
||||
LibOrder.Order[] memory orders,
|
||||
bytes[] memory signatures,
|
||||
LibOrder.Order[] memory feeOrders,
|
||||
bytes[] memory feeSignatures,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
public
|
||||
payable
|
||||
returns (
|
||||
LibFillResults.FillResults memory orderFillResults,
|
||||
LibFillResults.FillResults memory feeOrderFillResults
|
||||
);
|
||||
|
||||
/// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.
|
||||
/// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.
|
||||
/// Any ETH not spent will be refunded to sender.
|
||||
/// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to purchase.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.
|
||||
/// @param feeSignatures Proofs that feeOrders have been created by makers.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
/// @return Amounts filled and fees paid by maker and taker for both sets of orders.
|
||||
function marketBuyOrdersWithEth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures,
|
||||
LibOrder.Order[] memory feeOrders,
|
||||
bytes[] memory feeSignatures,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
public
|
||||
payable
|
||||
returns (
|
||||
LibFillResults.FillResults memory orderFillResults,
|
||||
LibFillResults.FillResults memory feeOrderFillResults
|
||||
);
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol";
|
||||
import "@0x/contracts-tokens/contracts/tokens/EtherToken/IEtherToken.sol";
|
||||
import "@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol";
|
||||
|
||||
|
||||
contract LibConstants {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256("ERC20Token(address)"));
|
||||
bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
|
||||
uint256 constant internal MAX_UINT = 2**256 - 1;
|
||||
uint256 constant internal PERCENTAGE_DENOMINATOR = 10**18;
|
||||
uint256 constant internal MAX_FEE_PERCENTAGE = 5 * PERCENTAGE_DENOMINATOR / 100; // 5%
|
||||
uint256 constant internal MAX_WETH_FILL_PERCENTAGE = 95 * PERCENTAGE_DENOMINATOR / 100; // 95%
|
||||
|
||||
// solhint-disable var-name-mixedcase
|
||||
IExchange internal EXCHANGE;
|
||||
IEtherToken internal ETHER_TOKEN;
|
||||
IERC20Token internal ZRX_TOKEN;
|
||||
bytes internal ZRX_ASSET_DATA;
|
||||
bytes internal WETH_ASSET_DATA;
|
||||
// solhint-enable var-name-mixedcase
|
||||
|
||||
constructor (
|
||||
address _exchange,
|
||||
bytes memory _zrxAssetData,
|
||||
bytes memory _wethAssetData
|
||||
)
|
||||
public
|
||||
{
|
||||
EXCHANGE = IExchange(_exchange);
|
||||
ZRX_ASSET_DATA = _zrxAssetData;
|
||||
WETH_ASSET_DATA = _wethAssetData;
|
||||
|
||||
address etherToken = _wethAssetData.readAddress(16);
|
||||
address zrxToken = _zrxAssetData.readAddress(16);
|
||||
ETHER_TOKEN = IEtherToken(etherToken);
|
||||
ZRX_TOKEN = IERC20Token(zrxToken);
|
||||
}
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
/// This contract is intended to serve as a reference, but is not actually used for efficiency reasons.
|
||||
contract LibForwarderErrors {
|
||||
string constant FEE_PERCENTAGE_TOO_LARGE = "FEE_PROPORTION_TOO_LARGE"; // Provided fee percentage greater than 5%.
|
||||
string constant INSUFFICIENT_ETH_REMAINING = "INSUFFICIENT_ETH_REMAINING"; // Not enough ETH remaining to pay feeRecipient.
|
||||
string constant OVERSOLD_WETH = "OVERSOLD_WETH"; // More WETH sold than provided with current message call.
|
||||
string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired purchase amount not completely filled (required for ZRX fees only).
|
||||
string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Asset transfer failed.
|
||||
string constant UNSUPPORTED_ASSET_PROXY = "UNSUPPORTED_ASSET_PROXY"; // Proxy in assetData not supported.
|
||||
string constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY = "DEFAULT_FUNCTION_WETH_CONTRACT_ONLY"; // Fallback function may only be used for WETH withdrawals.
|
||||
string constant INVALID_MSG_VALUE = "INVALID_MSG_VALUE"; // msg.value must be greater than 0.
|
||||
string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Amount must equal 1.
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "../interfaces/IAssets.sol";
|
||||
|
||||
|
||||
contract MAssets is
|
||||
IAssets
|
||||
{
|
||||
/// @dev Transfers given amount of asset to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferAssetToSender(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal;
|
||||
|
||||
/// @dev Decodes ERC20 assetData and transfers given amount to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferERC20Token(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal;
|
||||
|
||||
/// @dev Decodes ERC721 assetData and transfers given amount to sender.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param amount Amount of asset to transfer to sender.
|
||||
function transferERC721Token(
|
||||
bytes memory assetData,
|
||||
uint256 amount
|
||||
)
|
||||
internal;
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract MExchangeWrapper {
|
||||
|
||||
/// @dev Fills the input order.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrderNoThrow(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
internal
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of WETH has been sold by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param wethSellAmount Desired amount of WETH to sell.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 wethSellAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// The asset being sold by taker must always be WETH.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyExactAmountWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Buys zrxBuyAmount of ZRX fee tokens, taking into account ZRX fees for each order. This will guarantee
|
||||
/// that at least zrxBuyAmount of ZRX is purchased (sometimes slightly over due to rounding issues).
|
||||
/// It is possible that a request to buy 200 ZRX will require purchasing 202 ZRX
|
||||
/// as 2 ZRX is required to purchase the 200 ZRX fee tokens. This guarantees at least 200 ZRX for future purchases.
|
||||
/// The asset being sold by taker must always be WETH.
|
||||
/// @param orders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset.
|
||||
/// @param zrxBuyAmount Desired amount of ZRX to buy.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return totalFillResults Amounts filled and fees paid by maker and taker.
|
||||
function marketBuyExactZrxWithWeth(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 zrxBuyAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
internal
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract MWeth {
|
||||
|
||||
/// @dev Converts message call's ETH value into WETH.
|
||||
function convertEthToWeth()
|
||||
internal;
|
||||
|
||||
/// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.
|
||||
/// Refunds any excess ETH to msg.sender.
|
||||
/// @param wethSoldExcludingFeeOrders Amount of WETH sold when filling primary orders.
|
||||
/// @param wethSoldForZrx Amount of WETH sold when purchasing ZRX required for primary order fees.
|
||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||
function transferEthFeeAndRefund(
|
||||
uint256 wethSoldExcludingFeeOrders,
|
||||
uint256 wethSoldForZrx,
|
||||
uint256 feePercentage,
|
||||
address feeRecipient
|
||||
)
|
||||
internal;
|
||||
}
|
@@ -1,94 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0x/contracts-extensions",
|
||||
"version": "1.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Smart contract extensions of 0x protocol",
|
||||
"main": "lib/src/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"test": "yarn run_mocha",
|
||||
"rebuild_and_test": "run-s build test",
|
||||
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
|
||||
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||
"compile": "sol-compiler --contracts-dir contracts",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||
"coverage:report:lcov": "istanbul report lcov",
|
||||
"test:circleci": "yarn test",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "generated-artifacts/@(DutchAuction|Forwarder).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.19",
|
||||
"@0x/contracts-test-utils": "^1.0.2",
|
||||
"@0x/dev-utils": "^1.0.21",
|
||||
"@0x/sol-compiler": "^1.1.16",
|
||||
"@0x/sol-cov": "^2.1.16",
|
||||
"@0x/subproviders": "^2.1.8",
|
||||
"@0x/tslint-config": "^2.0.0",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.10",
|
||||
"@0x/contracts-interfaces": "^1.0.1",
|
||||
"@0x/contracts-libs": "^1.0.1",
|
||||
"@0x/contracts-protocol": "^2.1.58",
|
||||
"@0x/contracts-tokens": "^1.0.1",
|
||||
"@0x/contracts-utils": "^1.0.1",
|
||||
"@0x/order-utils": "^3.0.7",
|
||||
"@0x/types": "^1.4.1",
|
||||
"@0x/typescript-typings": "^3.0.6",
|
||||
"@0x/utils": "^2.0.8",
|
||||
"@0x/web3-wrapper": "^3.2.1",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^1.1.4",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as DutchAuction from '../../generated-artifacts/DutchAuction.json';
|
||||
import * as Forwarder from '../../generated-artifacts/Forwarder.json';
|
||||
|
||||
export const artifacts = {
|
||||
DutchAuction: DutchAuction as ContractArtifact,
|
||||
Forwarder: Forwarder as ContractArtifact,
|
||||
};
|
@@ -1,2 +0,0 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
@@ -1,2 +0,0 @@
|
||||
export * from '../../generated-wrappers/dutch_auction';
|
||||
export * from '../../generated-wrappers/forwarder';
|
@@ -1,458 +0,0 @@
|
||||
import {
|
||||
artifacts as protocolArtifacts,
|
||||
ERC20Wrapper,
|
||||
ERC721Wrapper,
|
||||
ExchangeContract,
|
||||
ExchangeWrapper,
|
||||
} from '@0x/contracts-protocol';
|
||||
import {
|
||||
chaiSetup,
|
||||
constants,
|
||||
ContractName,
|
||||
ERC20BalancesByOwner,
|
||||
expectTransactionFailedAsync,
|
||||
getLatestBlockTimestampAsync,
|
||||
OrderFactory,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import {
|
||||
artifacts as tokensArtifacts,
|
||||
DummyERC20TokenContract,
|
||||
DummyERC721TokenContract,
|
||||
WETH9Contract,
|
||||
} from '@0x/contracts-tokens';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
|
||||
import { RevertReason, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import ethAbi = require('ethereumjs-abi');
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
const DECIMALS_DEFAULT = 18;
|
||||
|
||||
describe(ContractName.DutchAuction, () => {
|
||||
let makerAddress: string;
|
||||
let owner: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipientAddress: string;
|
||||
let defaultMakerAssetAddress: string;
|
||||
|
||||
let zrxToken: DummyERC20TokenContract;
|
||||
let erc20TokenA: DummyERC20TokenContract;
|
||||
let erc721Token: DummyERC721TokenContract;
|
||||
let dutchAuctionContract: DutchAuctionContract;
|
||||
let wethContract: WETH9Contract;
|
||||
|
||||
let sellerOrderFactory: OrderFactory;
|
||||
let buyerOrderFactory: OrderFactory;
|
||||
let erc20Wrapper: ERC20Wrapper;
|
||||
let erc20Balances: ERC20BalancesByOwner;
|
||||
let currentBlockTimestamp: number;
|
||||
let auctionBeginTimeSeconds: BigNumber;
|
||||
let auctionEndTimeSeconds: BigNumber;
|
||||
let auctionBeginAmount: BigNumber;
|
||||
let auctionEndAmount: BigNumber;
|
||||
let sellOrder: SignedOrder;
|
||||
let buyOrder: SignedOrder;
|
||||
let erc721MakerAssetIds: BigNumber[];
|
||||
const tenMinutesInSeconds = 10 * 60;
|
||||
|
||||
function extendMakerAssetData(makerAssetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string {
|
||||
return ethUtil.bufferToHex(
|
||||
Buffer.concat([
|
||||
ethUtil.toBuffer(makerAssetData),
|
||||
ethUtil.toBuffer(
|
||||
(ethAbi as any).rawEncode(
|
||||
['uint256', 'uint256'],
|
||||
[beginTimeSeconds.toString(), beginAmount.toString()],
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
|
||||
|
||||
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
||||
|
||||
const numDummyErc20ToDeploy = 2;
|
||||
[erc20TokenA, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
|
||||
numDummyErc20ToDeploy,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
);
|
||||
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
|
||||
const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
|
||||
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
||||
const erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
||||
|
||||
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(tokensArtifacts.WETH9, provider, txDefaults);
|
||||
erc20Wrapper.addDummyTokenContract(wethContract as any);
|
||||
|
||||
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
protocolArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
zrxAssetData,
|
||||
);
|
||||
const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||
|
||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
||||
from: owner,
|
||||
});
|
||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
||||
from: owner,
|
||||
});
|
||||
|
||||
const dutchAuctionInstance = await DutchAuctionContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DutchAuction,
|
||||
provider,
|
||||
txDefaults,
|
||||
exchangeInstance.address,
|
||||
);
|
||||
dutchAuctionContract = new DutchAuctionContract(
|
||||
dutchAuctionInstance.abi,
|
||||
dutchAuctionInstance.address,
|
||||
provider,
|
||||
);
|
||||
|
||||
defaultMakerAssetAddress = erc20TokenA.address;
|
||||
const defaultTakerAssetAddress = wethContract.address;
|
||||
|
||||
// Set up taker WETH balance and allowance
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await wethContract.deposit.sendTransactionAsync({
|
||||
from: takerAddress,
|
||||
value: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
|
||||
}),
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await wethContract.approve.sendTransactionAsync(
|
||||
erc20Proxy.address,
|
||||
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
{ from: takerAddress },
|
||||
),
|
||||
);
|
||||
web3Wrapper.abiDecoder.addABI(exchangeInstance.abi);
|
||||
web3Wrapper.abiDecoder.addABI(zrxToken.abi);
|
||||
erc20Wrapper.addTokenOwnerAddress(dutchAuctionContract.address);
|
||||
|
||||
currentBlockTimestamp = await getLatestBlockTimestampAsync();
|
||||
// Default auction begins 10 minutes ago
|
||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp).minus(tenMinutesInSeconds);
|
||||
// Default auction ends 10 from now
|
||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds);
|
||||
auctionBeginAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT);
|
||||
auctionEndAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT);
|
||||
|
||||
// Default sell order and buy order are exact mirrors
|
||||
const sellerDefaultOrderParams = {
|
||||
salt: generatePseudoRandomSalt(),
|
||||
exchangeAddress: exchangeInstance.address,
|
||||
makerAddress,
|
||||
feeRecipientAddress,
|
||||
// taker address or sender address should be set to the ducth auction contract
|
||||
takerAddress: dutchAuctionContract.address,
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
|
||||
takerAssetAmount: auctionEndAmount,
|
||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||
makerFee: constants.ZERO_AMOUNT,
|
||||
takerFee: constants.ZERO_AMOUNT,
|
||||
};
|
||||
// Default buy order is for the auction begin price
|
||||
const buyerDefaultOrderParams = {
|
||||
...sellerDefaultOrderParams,
|
||||
makerAddress: takerAddress,
|
||||
makerAssetData: sellerDefaultOrderParams.takerAssetData,
|
||||
takerAssetData: sellerDefaultOrderParams.makerAssetData,
|
||||
makerAssetAmount: auctionBeginAmount,
|
||||
takerAssetAmount: sellerDefaultOrderParams.makerAssetAmount,
|
||||
};
|
||||
const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
||||
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
|
||||
sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
|
||||
buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
erc20Balances = await erc20Wrapper.getBalancesAsync();
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync();
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('matchOrders', () => {
|
||||
it('should be worth the begin price at the begining of the auction', async () => {
|
||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
});
|
||||
const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||
});
|
||||
it('should be be worth the end price at the end of the auction', async () => {
|
||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||
});
|
||||
const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount);
|
||||
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||
});
|
||||
it('should match orders at current amount and send excess to buyer', async () => {
|
||||
const beforeAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: beforeAuctionDetails.currentAmount.times(2),
|
||||
});
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
);
|
||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
// HACK gte used here due to a bug in ganache where the timestamp can change
|
||||
// between multiple calls to the same block. Which can move the amount in our case
|
||||
// ref: https://github.com/trufflesuite/ganache-core/issues/111
|
||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||
);
|
||||
expect(newBalances[takerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||
erc20Balances[takerAddress][wethContract.address].minus(beforeAuctionDetails.currentAmount),
|
||||
);
|
||||
});
|
||||
it('maker fees on sellOrder are paid to the fee receipient', async () => {
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
makerFee: new BigNumber(1),
|
||||
});
|
||||
const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||
);
|
||||
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
|
||||
erc20Balances[feeRecipientAddress][zrxToken.address].plus(sellOrder.makerFee),
|
||||
);
|
||||
});
|
||||
it('maker fees on buyOrder are paid to the fee receipient', async () => {
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
makerFee: new BigNumber(1),
|
||||
});
|
||||
const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||
);
|
||||
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
|
||||
erc20Balances[feeRecipientAddress][zrxToken.address].plus(buyOrder.makerFee),
|
||||
);
|
||||
});
|
||||
it('should revert when auction expires', async () => {
|
||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
RevertReason.AuctionExpired,
|
||||
);
|
||||
});
|
||||
it('cannot be filled for less than the current price', async () => {
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: sellOrder.takerAssetAmount,
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
RevertReason.AuctionInvalidAmount,
|
||||
);
|
||||
});
|
||||
it('auction begin amount must be higher than final amount ', async () => {
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
takerAssetAmount: auctionBeginAmount.plus(1),
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
RevertReason.AuctionInvalidAmount,
|
||||
);
|
||||
});
|
||||
it('begin time is less than end time', async () => {
|
||||
auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
RevertReason.AuctionInvalidBeginTime,
|
||||
);
|
||||
});
|
||||
it('asset data contains auction parameters', async () => {
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
RevertReason.InvalidAssetData,
|
||||
);
|
||||
});
|
||||
describe('ERC721', () => {
|
||||
it('should match orders when ERC721', async () => {
|
||||
const makerAssetId = erc721MakerAssetIds[0];
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
makerAssetData: extendMakerAssetData(
|
||||
assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
|
||||
auctionBeginTimeSeconds,
|
||||
auctionBeginAmount,
|
||||
),
|
||||
});
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
takerAssetData: sellOrder.makerAssetData,
|
||||
});
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
sellOrder,
|
||||
buyOrder.signature,
|
||||
sellOrder.signature,
|
||||
{
|
||||
from: takerAddress,
|
||||
},
|
||||
),
|
||||
);
|
||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||
// HACK gte used here due to a bug in ganache where the timestamp can change
|
||||
// between multiple calls to the same block. Which can move the amount in our case
|
||||
// ref: https://github.com/trufflesuite/ganache-core/issues/111
|
||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||
);
|
||||
const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
|
||||
expect(newOwner).to.be.bignumber.equal(takerAddress);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
import { env, EnvVars } from '@0x/dev-utils';
|
||||
|
||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||
before('start web3 provider', () => {
|
||||
provider.start();
|
||||
});
|
||||
after('generate coverage report', async () => {
|
||||
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
|
||||
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
|
||||
await coverageSubprovider.writeCoverageAsync();
|
||||
}
|
||||
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
|
||||
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
|
||||
await profilerSubprovider.writeProfilerOutputAsync();
|
||||
}
|
||||
provider.stop();
|
||||
});
|
@@ -1,124 +0,0 @@
|
||||
import { artifacts as protocolArtifacts } from '@0x/contracts-protocol';
|
||||
import { constants, formatters, LogDecoder, MarketSellOrders } from '@0x/contracts-test-utils';
|
||||
import { artifacts as tokensArtifacts } from '@0x/contracts-tokens';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { Provider, TransactionReceiptWithDecodedLogs, TxDataPayable } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ForwarderContract } from '../../generated-wrappers/forwarder';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
|
||||
export class ForwarderWrapper {
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _forwarderContract: ForwarderContract;
|
||||
private readonly _logDecoder: LogDecoder;
|
||||
public static getPercentageOfValue(value: BigNumber, percentage: number): BigNumber {
|
||||
const numerator = constants.PERCENTAGE_DENOMINATOR.times(percentage).dividedToIntegerBy(100);
|
||||
const newValue = value.times(numerator).dividedToIntegerBy(constants.PERCENTAGE_DENOMINATOR);
|
||||
return newValue;
|
||||
}
|
||||
public static getWethForFeeOrders(feeAmount: BigNumber, feeOrders: SignedOrder[]): BigNumber {
|
||||
let wethAmount = new BigNumber(0);
|
||||
let remainingFeeAmount = feeAmount;
|
||||
_.forEach(feeOrders, feeOrder => {
|
||||
const feeAvailable = feeOrder.makerAssetAmount.minus(feeOrder.takerFee);
|
||||
if (!remainingFeeAmount.isZero() && feeAvailable.gt(remainingFeeAmount)) {
|
||||
wethAmount = wethAmount.plus(
|
||||
feeOrder.takerAssetAmount
|
||||
.times(remainingFeeAmount)
|
||||
.dividedBy(feeAvailable)
|
||||
.ceil(),
|
||||
);
|
||||
remainingFeeAmount = new BigNumber(0);
|
||||
} else if (!remainingFeeAmount.isZero()) {
|
||||
wethAmount = wethAmount.plus(feeOrder.takerAssetAmount);
|
||||
remainingFeeAmount = remainingFeeAmount.minus(feeAvailable);
|
||||
}
|
||||
});
|
||||
return wethAmount;
|
||||
}
|
||||
private static _createOptimizedOrders(signedOrders: SignedOrder[]): MarketSellOrders {
|
||||
_.forEach(signedOrders, (signedOrder, index) => {
|
||||
signedOrder.takerAssetData = constants.NULL_BYTES;
|
||||
if (index > 0) {
|
||||
signedOrder.makerAssetData = constants.NULL_BYTES;
|
||||
}
|
||||
});
|
||||
const params = formatters.createMarketSellOrders(signedOrders, constants.ZERO_AMOUNT);
|
||||
return params;
|
||||
}
|
||||
private static _createOptimizedZrxOrders(signedOrders: SignedOrder[]): MarketSellOrders {
|
||||
_.forEach(signedOrders, signedOrder => {
|
||||
signedOrder.makerAssetData = constants.NULL_BYTES;
|
||||
signedOrder.takerAssetData = constants.NULL_BYTES;
|
||||
});
|
||||
const params = formatters.createMarketSellOrders(signedOrders, constants.ZERO_AMOUNT);
|
||||
return params;
|
||||
}
|
||||
constructor(contractInstance: ForwarderContract, provider: Provider) {
|
||||
this._forwarderContract = contractInstance;
|
||||
this._web3Wrapper = new Web3Wrapper(provider);
|
||||
this._logDecoder = new LogDecoder(this._web3Wrapper, {
|
||||
...artifacts,
|
||||
...tokensArtifacts,
|
||||
...protocolArtifacts,
|
||||
});
|
||||
}
|
||||
public async marketSellOrdersWithEthAsync(
|
||||
orders: SignedOrder[],
|
||||
feeOrders: SignedOrder[],
|
||||
txData: TxDataPayable,
|
||||
opts: { feePercentage?: BigNumber; feeRecipient?: string } = {},
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const params = ForwarderWrapper._createOptimizedOrders(orders);
|
||||
const feeParams = ForwarderWrapper._createOptimizedZrxOrders(feeOrders);
|
||||
const feePercentage = _.isUndefined(opts.feePercentage) ? constants.ZERO_AMOUNT : opts.feePercentage;
|
||||
const feeRecipient = _.isUndefined(opts.feeRecipient) ? constants.NULL_ADDRESS : opts.feeRecipient;
|
||||
const txHash = await this._forwarderContract.marketSellOrdersWithEth.sendTransactionAsync(
|
||||
params.orders,
|
||||
params.signatures,
|
||||
feeParams.orders,
|
||||
feeParams.signatures,
|
||||
feePercentage,
|
||||
feeRecipient,
|
||||
txData,
|
||||
);
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async marketBuyOrdersWithEthAsync(
|
||||
orders: SignedOrder[],
|
||||
feeOrders: SignedOrder[],
|
||||
makerAssetFillAmount: BigNumber,
|
||||
txData: TxDataPayable,
|
||||
opts: { feePercentage?: BigNumber; feeRecipient?: string } = {},
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const params = ForwarderWrapper._createOptimizedOrders(orders);
|
||||
const feeParams = ForwarderWrapper._createOptimizedZrxOrders(feeOrders);
|
||||
const feePercentage = _.isUndefined(opts.feePercentage) ? constants.ZERO_AMOUNT : opts.feePercentage;
|
||||
const feeRecipient = _.isUndefined(opts.feeRecipient) ? constants.NULL_ADDRESS : opts.feeRecipient;
|
||||
const txHash = await this._forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
|
||||
params.orders,
|
||||
makerAssetFillAmount,
|
||||
params.signatures,
|
||||
feeParams.orders,
|
||||
feeParams.signatures,
|
||||
feePercentage,
|
||||
feeRecipient,
|
||||
txData,
|
||||
);
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async withdrawAssetAsync(
|
||||
assetData: string,
|
||||
amount: BigNumber,
|
||||
txData: TxDataPayable,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._forwarderContract.withdrawAsset.sendTransactionAsync(assetData, amount, txData);
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": ["./generated-artifacts/DutchAuction.json", "./generated-artifacts/Forwarder.json"],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
## Contract interfaces
|
||||
|
||||
Smart contract interfaces of the 0x protocol.
|
||||
|
||||
## Usage
|
||||
|
||||
Contracts that make up and interact with version 2.0.0 of the protocol can be found in the [contracts](./contracts) directory. The contents of this directory are broken down into the following subdirectories:
|
||||
|
||||
* [protocol](./contracts/protocol)
|
||||
* This directory contains the contract interfaces that make up version 2.0.0. A full specification can be found [here](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
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/contracts-interfaces yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-interfaces yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"compilerSettings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": [
|
||||
"IAssetData",
|
||||
"IAssetProxy",
|
||||
"IAuthorizable",
|
||||
"IAssetProxyDispatcher",
|
||||
"IExchange",
|
||||
"IExchangeCore",
|
||||
"IMatchOrders",
|
||||
"ISignatureValidator",
|
||||
"ITransactions",
|
||||
"IValidator",
|
||||
"IWallet",
|
||||
"IWrapperFunctions"
|
||||
]
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
// @dev Interface of the asset proxy's assetData.
|
||||
// The asset proxies take an ABI encoded `bytes assetData` as argument.
|
||||
// This argument is ABI encoded as one of the methods of this interface.
|
||||
interface IAssetData {
|
||||
|
||||
function ERC20Token(address tokenContract)
|
||||
external;
|
||||
|
||||
function ERC721Token(
|
||||
address tokenContract,
|
||||
uint256 tokenId
|
||||
)
|
||||
external;
|
||||
|
||||
function MultiAsset(
|
||||
uint256[] amounts,
|
||||
bytes[] nestedAssetData
|
||||
)
|
||||
external;
|
||||
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "./IAuthorizable.sol";
|
||||
|
||||
|
||||
contract IAssetProxy is
|
||||
IAuthorizable
|
||||
{
|
||||
/// @dev Transfers assets. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param from Address to transfer asset from.
|
||||
/// @param to Address to transfer asset to.
|
||||
/// @param amount Amount of asset to transfer.
|
||||
function transferFrom(
|
||||
bytes assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4);
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-utils/contracts/utils/Ownable/IOwnable.sol";
|
||||
|
||||
|
||||
contract IAuthorizable is
|
||||
IOwnable
|
||||
{
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract IAssetProxyDispatcher {
|
||||
|
||||
/// @dev Registers an asset proxy to its asset proxy id.
|
||||
/// Once an asset proxy is registered, it cannot be unregistered.
|
||||
/// @param assetProxy Address of new asset proxy to register.
|
||||
function registerAssetProxy(address assetProxy)
|
||||
external;
|
||||
|
||||
/// @dev Gets an asset proxy.
|
||||
/// @param assetProxyId Id of the asset proxy.
|
||||
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
|
||||
function getAssetProxy(bytes4 assetProxyId)
|
||||
external
|
||||
view
|
||||
returns (address);
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./IExchangeCore.sol";
|
||||
import "./IMatchOrders.sol";
|
||||
import "./ISignatureValidator.sol";
|
||||
import "./ITransactions.sol";
|
||||
import "./IAssetProxyDispatcher.sol";
|
||||
import "./IWrapperFunctions.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract IExchange is
|
||||
IExchangeCore,
|
||||
IMatchOrders,
|
||||
ISignatureValidator,
|
||||
ITransactions,
|
||||
IAssetProxyDispatcher,
|
||||
IWrapperFunctions
|
||||
{}
|
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IExchangeCore {
|
||||
|
||||
/// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch
|
||||
/// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress).
|
||||
/// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled.
|
||||
function cancelOrdersUpTo(uint256 targetOrderEpoch)
|
||||
external;
|
||||
|
||||
/// @dev Fills the input order.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev After calling, the order can not be filled anymore.
|
||||
/// @param order Order struct containing order specifications.
|
||||
function cancelOrder(LibOrder.Order memory order)
|
||||
public;
|
||||
|
||||
/// @dev Gets information about an order: status, hash, and amount filled.
|
||||
/// @param order Order to gather information on.
|
||||
/// @return OrderInfo Information about the order and its state.
|
||||
/// See LibOrder.OrderInfo for a complete description.
|
||||
function getOrderInfo(LibOrder.Order memory order)
|
||||
public
|
||||
view
|
||||
returns (LibOrder.OrderInfo memory orderInfo);
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IMatchOrders {
|
||||
|
||||
/// @dev Match two complementary orders that have a profitable spread.
|
||||
/// Each order is filled at their respective price point. However, the calculations are
|
||||
/// carried out as though the orders are both being filled at the right order's price point.
|
||||
/// The profit made by the left order goes to the taker (who matched the two orders).
|
||||
/// @param leftOrder First order to match.
|
||||
/// @param rightOrder Second order to match.
|
||||
/// @param leftSignature Proof that order was created by the left maker.
|
||||
/// @param rightSignature Proof that order was created by the right maker.
|
||||
/// @return matchedFillResults Amounts filled and fees paid by maker and taker of matched orders.
|
||||
function matchOrders(
|
||||
LibOrder.Order memory leftOrder,
|
||||
LibOrder.Order memory rightOrder,
|
||||
bytes memory leftSignature,
|
||||
bytes memory rightSignature
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.MatchedFillResults memory matchedFillResults);
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract ISignatureValidator {
|
||||
|
||||
/// @dev Approves a hash on-chain using any valid signature type.
|
||||
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
|
||||
/// @param signerAddress Address that should have signed the given hash.
|
||||
/// @param signature Proof that the hash has been signed by signer.
|
||||
function preSign(
|
||||
bytes32 hash,
|
||||
address signerAddress,
|
||||
bytes signature
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf.
|
||||
/// @param validatorAddress Address of Validator contract.
|
||||
/// @param approval Approval or disapproval of Validator contract.
|
||||
function setSignatureValidatorApproval(
|
||||
address validatorAddress,
|
||||
bool approval
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Verifies that a signature is valid.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param signerAddress Address of signer.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of order signature.
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
address signerAddress,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (bool isValid);
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract ITransactions {
|
||||
|
||||
/// @dev Executes an exchange method call in the context of signer.
|
||||
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
|
||||
/// @param signerAddress Address of transaction signer.
|
||||
/// @param data AbiV2 encoded calldata.
|
||||
/// @param signature Proof of signer transaction by signer.
|
||||
function executeTransaction(
|
||||
uint256 salt,
|
||||
address signerAddress,
|
||||
bytes data,
|
||||
bytes signature
|
||||
)
|
||||
external;
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract IValidator {
|
||||
|
||||
/// @dev Verifies that a signature is valid.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param signerAddress Address that should have signed the given hash.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of order signature.
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
address signerAddress,
|
||||
bytes signature
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isValid);
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract IWallet {
|
||||
|
||||
/// @dev Verifies that a signature is valid.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of order signature.
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
bytes signature
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isValid);
|
||||
}
|
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IWrapperFunctions {
|
||||
|
||||
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
|
||||
/// @param order LibOrder.Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
function fillOrKillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param order LibOrder.Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrderNoThrow(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function batchFillOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrKill.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function batchFillOrKillOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function batchFillOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of makerAsset is bought by taker.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously cancels multiple orders in a single transaction.
|
||||
/// @param orders Array of order specifications.
|
||||
function batchCancelOrders(LibOrder.Order[] memory orders)
|
||||
public;
|
||||
|
||||
/// @dev Fetches information for all passed in orders
|
||||
/// @param orders Array of order specifications.
|
||||
/// @return Array of OrderInfo instances that correspond to each order.
|
||||
function getOrdersInfo(LibOrder.Order[] memory orders)
|
||||
public
|
||||
view
|
||||
returns (LibOrder.OrderInfo[] memory);
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0x/contracts-interfaces",
|
||||
"version": "1.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Smart contract interfaces of 0x protocol",
|
||||
"main": "lib/src/index.js",
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"compile": "sol-compiler --contracts-dir contracts",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "generated-artifacts/@(IAssetData|IAssetProxy|IAuthorizable|IAssetProxyDispatcher|IExchange|IExchangeCore|IMatchOrders|ISignatureValidator|ITransactions|IValidator|IWallet|IWrapperFunctions).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/interfaces/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.19",
|
||||
"@0x/sol-compiler": "^1.1.16",
|
||||
"@0x/tslint-config": "^2.0.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.10",
|
||||
"@0x/contracts-libs": "^1.0.1",
|
||||
"@0x/contracts-utils": "^1.0.1",
|
||||
"@0x/types": "^1.4.1",
|
||||
"@0x/typescript-typings": "^3.0.6",
|
||||
"@0x/utils": "^2.0.8",
|
||||
"@0x/web3-wrapper": "^3.2.1",
|
||||
"ethereum-types": "^1.1.4",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as IAssetData from '../../generated-artifacts/IAssetData.json';
|
||||
import * as IAssetProxy from '../../generated-artifacts/IAssetProxy.json';
|
||||
import * as IAssetProxyDispatcher from '../../generated-artifacts/IAssetProxyDispatcher.json';
|
||||
import * as IAuthorizable from '../../generated-artifacts/IAuthorizable.json';
|
||||
import * as IExchange from '../../generated-artifacts/IExchange.json';
|
||||
import * as IExchangeCore from '../../generated-artifacts/IExchangeCore.json';
|
||||
import * as IMatchOrders from '../../generated-artifacts/IMatchOrders.json';
|
||||
import * as ISignatureValidator from '../../generated-artifacts/ISignatureValidator.json';
|
||||
import * as ITransactions from '../../generated-artifacts/ITransactions.json';
|
||||
import * as IValidator from '../../generated-artifacts/IValidator.json';
|
||||
import * as IWallet from '../../generated-artifacts/IWallet.json';
|
||||
import * as IWrapperFunctions from '../../generated-artifacts/IWrapperFunctions.json';
|
||||
|
||||
export const artifacts = {
|
||||
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||
IExchange: IExchange as ContractArtifact,
|
||||
IExchangeCore: IExchangeCore as ContractArtifact,
|
||||
IMatchOrders: IMatchOrders as ContractArtifact,
|
||||
ISignatureValidator: ISignatureValidator as ContractArtifact,
|
||||
ITransactions: ITransactions as ContractArtifact,
|
||||
IWrapperFunctions: IWrapperFunctions as ContractArtifact,
|
||||
IAssetData: IAssetData as ContractArtifact,
|
||||
IAssetProxy: IAssetProxy as ContractArtifact,
|
||||
IValidator: IValidator as ContractArtifact,
|
||||
IWallet: IWallet as ContractArtifact,
|
||||
};
|
@@ -1,2 +0,0 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
@@ -1,12 +0,0 @@
|
||||
export * from '../../generated-wrappers/i_asset_data';
|
||||
export * from '../../generated-wrappers/i_asset_proxy';
|
||||
export * from '../../generated-wrappers/i_asset_proxy_dispatcher';
|
||||
export * from '../../generated-wrappers/i_exchange';
|
||||
export * from '../../generated-wrappers/i_exchange_core';
|
||||
export * from '../../generated-wrappers/i_match_orders';
|
||||
export * from '../../generated-wrappers/i_signature_validator';
|
||||
export * from '../../generated-wrappers/i_transactions';
|
||||
export * from '../../generated-wrappers/i_authorizable';
|
||||
export * from '../../generated-wrappers/i_wrapper_functions';
|
||||
export * from '../../generated-wrappers/i_validator';
|
||||
export * from '../../generated-wrappers/i_wallet';
|
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./src/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"./generated-artifacts/IAssetData.json",
|
||||
"./generated-artifacts/IAssetProxy.json",
|
||||
"./generated-artifacts/IAuthorizable.json",
|
||||
"./generated-artifacts/IAssetProxyDispatcher.json",
|
||||
"./generated-artifacts/IExchange.json",
|
||||
"./generated-artifacts/IExchangeCore.json",
|
||||
"./generated-artifacts/IMatchOrders.json",
|
||||
"./generated-artifacts/ISignatureValidator.json",
|
||||
"./generated-artifacts/ITransactions.json",
|
||||
"./generated-artifacts/IValidator.json",
|
||||
"./generated-artifacts/IWallet.json",
|
||||
"./generated-artifacts/IWrapperFunctions.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"compilerSettings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": ["TestLibs", "LibOrder", "LibMath", "LibFillResults", "LibAbiEncoder", "LibEIP712"]
|
||||
}
|
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./LibOrder.sol";
|
||||
|
||||
|
||||
contract LibAbiEncoder {
|
||||
|
||||
/// @dev ABI encodes calldata for `fillOrder`.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return ABI encoded calldata for `fillOrder`.
|
||||
function abiEncodeFillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory fillOrderCalldata)
|
||||
{
|
||||
// We need to call MExchangeCore.fillOrder using a delegatecall in
|
||||
// assembly so that we can intercept a call that throws. For this, we
|
||||
// need the input encoded in memory in the Ethereum ABIv2 format [1].
|
||||
|
||||
// | Area | Offset | Length | Contents |
|
||||
// | -------- |--------|---------|-------------------------------------------- |
|
||||
// | Header | 0x00 | 4 | function selector |
|
||||
// | Params | | 3 * 32 | function parameters: |
|
||||
// | | 0x00 | | 1. offset to order (*) |
|
||||
// | | 0x20 | | 2. takerAssetFillAmount |
|
||||
// | | 0x40 | | 3. offset to signature (*) |
|
||||
// | Data | | 12 * 32 | order: |
|
||||
// | | 0x000 | | 1. senderAddress |
|
||||
// | | 0x020 | | 2. makerAddress |
|
||||
// | | 0x040 | | 3. takerAddress |
|
||||
// | | 0x060 | | 4. feeRecipientAddress |
|
||||
// | | 0x080 | | 5. makerAssetAmount |
|
||||
// | | 0x0A0 | | 6. takerAssetAmount |
|
||||
// | | 0x0C0 | | 7. makerFeeAmount |
|
||||
// | | 0x0E0 | | 8. takerFeeAmount |
|
||||
// | | 0x100 | | 9. expirationTimeSeconds |
|
||||
// | | 0x120 | | 10. salt |
|
||||
// | | 0x140 | | 11. Offset to makerAssetData (*) |
|
||||
// | | 0x160 | | 12. Offset to takerAssetData (*) |
|
||||
// | | 0x180 | 32 | makerAssetData Length |
|
||||
// | | 0x1A0 | ** | makerAssetData Contents |
|
||||
// | | 0x1C0 | 32 | takerAssetData Length |
|
||||
// | | 0x1E0 | ** | takerAssetData Contents |
|
||||
// | | 0x200 | 32 | signature Length |
|
||||
// | | 0x220 | ** | signature Contents |
|
||||
|
||||
// * Offsets are calculated from the beginning of the current area: Header, Params, Data:
|
||||
// An offset stored in the Params area is calculated from the beginning of the Params section.
|
||||
// An offset stored in the Data area is calculated from the beginning of the Data section.
|
||||
|
||||
// ** The length of dynamic array contents are stored in the field immediately preceeding the contents.
|
||||
|
||||
// [1]: https://solidity.readthedocs.io/en/develop/abi-spec.html
|
||||
|
||||
assembly {
|
||||
|
||||
// Areas below may use the following variables:
|
||||
// 1. <area>Start -- Start of this area in memory
|
||||
// 2. <area>End -- End of this area in memory. This value may
|
||||
// be precomputed (before writing contents),
|
||||
// or it may be computed as contents are written.
|
||||
// 3. <area>Offset -- Current offset into area. If an area's End
|
||||
// is precomputed, this variable tracks the
|
||||
// offsets of contents as they are written.
|
||||
|
||||
/////// Setup Header Area ///////
|
||||
// Load free memory pointer
|
||||
fillOrderCalldata := mload(0x40)
|
||||
// bytes4(keccak256("fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),uint256,bytes)"))
|
||||
// = 0xb4be83d5
|
||||
// Leave 0x20 bytes to store the length
|
||||
mstore(add(fillOrderCalldata, 0x20), 0xb4be83d500000000000000000000000000000000000000000000000000000000)
|
||||
let headerAreaEnd := add(fillOrderCalldata, 0x24)
|
||||
|
||||
/////// Setup Params Area ///////
|
||||
// This area is preallocated and written to later.
|
||||
// This is because we need to fill in offsets that have not yet been calculated.
|
||||
let paramsAreaStart := headerAreaEnd
|
||||
let paramsAreaEnd := add(paramsAreaStart, 0x60)
|
||||
let paramsAreaOffset := paramsAreaStart
|
||||
|
||||
/////// Setup Data Area ///////
|
||||
let dataAreaStart := paramsAreaEnd
|
||||
let dataAreaEnd := dataAreaStart
|
||||
|
||||
// Offset from the source data we're reading from
|
||||
let sourceOffset := order
|
||||
// arrayLenBytes and arrayLenWords track the length of a dynamically-allocated bytes array.
|
||||
let arrayLenBytes := 0
|
||||
let arrayLenWords := 0
|
||||
|
||||
/////// Write order Struct ///////
|
||||
// Write memory location of Order, relative to the start of the
|
||||
// parameter list, then increment the paramsAreaOffset respectively.
|
||||
mstore(paramsAreaOffset, sub(dataAreaEnd, paramsAreaStart))
|
||||
paramsAreaOffset := add(paramsAreaOffset, 0x20)
|
||||
|
||||
// Write values for each field in the order
|
||||
// It would be nice to use a loop, but we save on gas by writing
|
||||
// the stores sequentially.
|
||||
mstore(dataAreaEnd, mload(sourceOffset)) // makerAddress
|
||||
mstore(add(dataAreaEnd, 0x20), mload(add(sourceOffset, 0x20))) // takerAddress
|
||||
mstore(add(dataAreaEnd, 0x40), mload(add(sourceOffset, 0x40))) // feeRecipientAddress
|
||||
mstore(add(dataAreaEnd, 0x60), mload(add(sourceOffset, 0x60))) // senderAddress
|
||||
mstore(add(dataAreaEnd, 0x80), mload(add(sourceOffset, 0x80))) // makerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0xA0), mload(add(sourceOffset, 0xA0))) // takerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0xC0), mload(add(sourceOffset, 0xC0))) // makerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // takerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // expirationTimeSeconds
|
||||
mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // salt
|
||||
mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetData
|
||||
mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetData
|
||||
dataAreaEnd := add(dataAreaEnd, 0x180)
|
||||
sourceOffset := add(sourceOffset, 0x180)
|
||||
|
||||
// Write offset to <order.makerAssetData>
|
||||
mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
|
||||
// Calculate length of <order.makerAssetData>
|
||||
sourceOffset := mload(add(order, 0x140)) // makerAssetData
|
||||
arrayLenBytes := mload(sourceOffset)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20)
|
||||
|
||||
// Write length of <order.makerAssetData>
|
||||
mstore(dataAreaEnd, arrayLenBytes)
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
|
||||
// Write contents of <order.makerAssetData>
|
||||
for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} {
|
||||
mstore(dataAreaEnd, mload(sourceOffset))
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
}
|
||||
|
||||
// Write offset to <order.takerAssetData>
|
||||
mstore(add(dataAreaStart, mul(11, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
|
||||
// Calculate length of <order.takerAssetData>
|
||||
sourceOffset := mload(add(order, 0x160)) // takerAssetData
|
||||
arrayLenBytes := mload(sourceOffset)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20)
|
||||
|
||||
// Write length of <order.takerAssetData>
|
||||
mstore(dataAreaEnd, arrayLenBytes)
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
|
||||
// Write contents of <order.takerAssetData>
|
||||
for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} {
|
||||
mstore(dataAreaEnd, mload(sourceOffset))
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
}
|
||||
|
||||
/////// Write takerAssetFillAmount ///////
|
||||
mstore(paramsAreaOffset, takerAssetFillAmount)
|
||||
paramsAreaOffset := add(paramsAreaOffset, 0x20)
|
||||
|
||||
/////// Write signature ///////
|
||||
// Write offset to paramsArea
|
||||
mstore(paramsAreaOffset, sub(dataAreaEnd, paramsAreaStart))
|
||||
|
||||
// Calculate length of signature
|
||||
sourceOffset := signature
|
||||
arrayLenBytes := mload(sourceOffset)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20)
|
||||
|
||||
// Write length of signature
|
||||
mstore(dataAreaEnd, arrayLenBytes)
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
|
||||
// Write contents of signature
|
||||
for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} {
|
||||
mstore(dataAreaEnd, mload(sourceOffset))
|
||||
dataAreaEnd := add(dataAreaEnd, 0x20)
|
||||
sourceOffset := add(sourceOffset, 0x20)
|
||||
}
|
||||
|
||||
// Set length of calldata
|
||||
mstore(fillOrderCalldata, sub(dataAreaEnd, add(fillOrderCalldata, 0x20)))
|
||||
|
||||
// Increment free memory pointer
|
||||
mstore(0x40, dataAreaEnd)
|
||||
}
|
||||
|
||||
return fillOrderCalldata;
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
/// @dev This contract documents the revert reasons used in the AssetProxy contracts.
|
||||
/// This contract is intended to serve as a reference, but is not actually used for efficiency reasons.
|
||||
contract LibAssetProxyErrors {
|
||||
|
||||
/// Authorizable errors ///
|
||||
string constant SENDER_NOT_AUTHORIZED = "SENDER_NOT_AUTHORIZED"; // Sender not authorized to call this method.
|
||||
string constant TARGET_NOT_AUTHORIZED = "TARGET_NOT_AUTHORIZED"; // Target address not authorized to call this method.
|
||||
string constant TARGET_ALREADY_AUTHORIZED = "TARGET_ALREADY_AUTHORIZED"; // Target address must not already be authorized.
|
||||
string constant INDEX_OUT_OF_BOUNDS = "INDEX_OUT_OF_BOUNDS"; // Specified array index is out of bounds.
|
||||
string constant AUTHORIZED_ADDRESS_MISMATCH = "AUTHORIZED_ADDRESS_MISMATCH"; // Address at index does not match given target address.
|
||||
|
||||
/// Transfer errors ///
|
||||
string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1.
|
||||
string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed.
|
||||
string constant LENGTH_GREATER_THAN_131_REQUIRED = "LENGTH_GREATER_THAN_131_REQUIRED"; // Byte array must have a length greater than 0.
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
// solhint-disable max-line-length
|
||||
contract LibConstants {
|
||||
|
||||
// Asset data for ZRX token. Used for fee transfers.
|
||||
// @TODO: Hardcode constant when we deploy. Currently
|
||||
// not constant to make testing easier.
|
||||
|
||||
// The proxyId for ZRX_ASSET_DATA is bytes4(keccak256("ERC20Token(address)")) = 0xf47261b0
|
||||
|
||||
// Kovan ZRX address is 0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570.
|
||||
// The ABI encoded proxyId and address is 0xf47261b00000000000000000000000006ff6c0ff1d68b964901f986d4c9fa3ac68346570
|
||||
// bytes constant public ZRX_ASSET_DATA = "\xf4\x72\x61\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6f\xf6\xc0\xff\x1d\x68\xb9\x64\x90\x1f\x98\x6d\x4c\x9f\xa3\xac\x68\x34\x65\x70";
|
||||
|
||||
// Mainnet ZRX address is 0xe41d2489571d322189246dafa5ebde1f4699f498.
|
||||
// The ABI encoded proxyId and address is 0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498
|
||||
// bytes constant public ZRX_ASSET_DATA = "\xf4\x72\x61\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe4\x1d\x24\x89\x57\x1d\x32\x21\x89\x24\x6d\xaf\xa5\xeb\xde\x1f\x46\x99\xf4\x98";
|
||||
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
bytes public ZRX_ASSET_DATA;
|
||||
|
||||
// @TODO: Remove when we deploy.
|
||||
constructor (bytes memory zrxAssetData)
|
||||
public
|
||||
{
|
||||
ZRX_ASSET_DATA = zrxAssetData;
|
||||
}
|
||||
}
|
||||
// solhint-enable max-line-length
|
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
contract LibEIP712 {
|
||||
|
||||
// EIP191 header for EIP712 prefix
|
||||
string constant internal EIP191_HEADER = "\x19\x01";
|
||||
|
||||
// EIP712 Domain Name value
|
||||
string constant internal EIP712_DOMAIN_NAME = "0x Protocol";
|
||||
|
||||
// EIP712 Domain Version value
|
||||
string constant internal EIP712_DOMAIN_VERSION = "2";
|
||||
|
||||
// Hash of the EIP712 Domain Separator Schema
|
||||
bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
|
||||
"EIP712Domain(",
|
||||
"string name,",
|
||||
"string version,",
|
||||
"address verifyingContract",
|
||||
")"
|
||||
));
|
||||
|
||||
// Hash of the EIP712 Domain Separator data
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
bytes32 public EIP712_DOMAIN_HASH;
|
||||
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(
|
||||
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
|
||||
keccak256(bytes(EIP712_DOMAIN_NAME)),
|
||||
keccak256(bytes(EIP712_DOMAIN_VERSION)),
|
||||
bytes32(address(this))
|
||||
));
|
||||
}
|
||||
|
||||
/// @dev Calculates EIP712 encoding for a hash struct in this EIP712 Domain.
|
||||
/// @param hashStruct The EIP712 hash struct.
|
||||
/// @return EIP712 hash applied to this EIP712 Domain.
|
||||
function hashEIP712Message(bytes32 hashStruct)
|
||||
internal
|
||||
view
|
||||
returns (bytes32 result)
|
||||
{
|
||||
bytes32 eip712DomainHash = EIP712_DOMAIN_HASH;
|
||||
|
||||
// Assembly for more efficient computing:
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP191_HEADER,
|
||||
// EIP712_DOMAIN_HASH,
|
||||
// hashStruct
|
||||
// ));
|
||||
|
||||
assembly {
|
||||
// Load free memory pointer
|
||||
let memPtr := mload(64)
|
||||
|
||||
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
|
||||
mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
|
||||
mstore(add(memPtr, 34), hashStruct) // Hash of struct
|
||||
|
||||
// Compute hash
|
||||
result := keccak256(memPtr, 66)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
/// @dev This contract documents the revert reasons used in the Exchange contract.
|
||||
/// This contract is intended to serve as a reference, but is not actually used for efficiency reasons.
|
||||
contract LibExchangeErrors {
|
||||
|
||||
/// Order validation errors ///
|
||||
string constant ORDER_UNFILLABLE = "ORDER_UNFILLABLE"; // Order cannot be filled.
|
||||
string constant INVALID_MAKER = "INVALID_MAKER"; // Invalid makerAddress.
|
||||
string constant INVALID_TAKER = "INVALID_TAKER"; // Invalid takerAddress.
|
||||
string constant INVALID_SENDER = "INVALID_SENDER"; // Invalid `msg.sender`.
|
||||
string constant INVALID_ORDER_SIGNATURE = "INVALID_ORDER_SIGNATURE"; // Signature validation failed.
|
||||
|
||||
/// fillOrder validation errors ///
|
||||
string constant INVALID_TAKER_AMOUNT = "INVALID_TAKER_AMOUNT"; // takerAssetFillAmount cannot equal 0.
|
||||
string constant ROUNDING_ERROR = "ROUNDING_ERROR"; // Rounding error greater than 0.1% of takerAssetFillAmount.
|
||||
|
||||
/// Signature validation errors ///
|
||||
string constant INVALID_SIGNATURE = "INVALID_SIGNATURE"; // Signature validation failed.
|
||||
string constant SIGNATURE_ILLEGAL = "SIGNATURE_ILLEGAL"; // Signature type is illegal.
|
||||
string constant SIGNATURE_UNSUPPORTED = "SIGNATURE_UNSUPPORTED"; // Signature type unsupported.
|
||||
|
||||
/// cancelOrdersUptTo errors ///
|
||||
string constant INVALID_NEW_ORDER_EPOCH = "INVALID_NEW_ORDER_EPOCH"; // Specified salt must be greater than or equal to existing orderEpoch.
|
||||
|
||||
/// fillOrKillOrder errors ///
|
||||
string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired takerAssetFillAmount could not be completely filled.
|
||||
|
||||
/// matchOrders errors ///
|
||||
string constant NEGATIVE_SPREAD_REQUIRED = "NEGATIVE_SPREAD_REQUIRED"; // Matched orders must have a negative spread.
|
||||
|
||||
/// Transaction errors ///
|
||||
string constant REENTRANCY_ILLEGAL = "REENTRANCY_ILLEGAL"; // Recursive reentrancy is not allowed.
|
||||
string constant INVALID_TX_HASH = "INVALID_TX_HASH"; // Transaction has already been executed.
|
||||
string constant INVALID_TX_SIGNATURE = "INVALID_TX_SIGNATURE"; // Signature validation failed.
|
||||
string constant FAILED_EXECUTION = "FAILED_EXECUTION"; // Transaction execution failed.
|
||||
|
||||
/// registerAssetProxy errors ///
|
||||
string constant ASSET_PROXY_ALREADY_EXISTS = "ASSET_PROXY_ALREADY_EXISTS"; // AssetProxy with same id already exists.
|
||||
|
||||
/// dispatchTransferFrom errors ///
|
||||
string constant ASSET_PROXY_DOES_NOT_EXIST = "ASSET_PROXY_DOES_NOT_EXIST"; // No assetProxy registered at given id.
|
||||
string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Asset transfer unsuccesful.
|
||||
|
||||
/// Length validation errors ///
|
||||
string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0.
|
||||
string constant LENGTH_GREATER_THAN_3_REQUIRED = "LENGTH_GREATER_THAN_3_REQUIRED"; // Byte array must have a length greater than 3.
|
||||
string constant LENGTH_0_REQUIRED = "LENGTH_0_REQUIRED"; // Byte array must have a length of 0.
|
||||
string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; // Byte array must have a length of 65.
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
|
||||
|
||||
|
||||
contract LibFillResults is
|
||||
SafeMath
|
||||
{
|
||||
struct FillResults {
|
||||
uint256 makerAssetFilledAmount; // Total amount of makerAsset(s) filled.
|
||||
uint256 takerAssetFilledAmount; // Total amount of takerAsset(s) filled.
|
||||
uint256 makerFeePaid; // Total amount of ZRX paid by maker(s) to feeRecipient(s).
|
||||
uint256 takerFeePaid; // Total amount of ZRX paid by taker to feeRecipients(s).
|
||||
}
|
||||
|
||||
struct MatchedFillResults {
|
||||
FillResults left; // Amounts filled and fees paid of left order.
|
||||
FillResults right; // Amounts filled and fees paid of right order.
|
||||
uint256 leftMakerAssetSpreadAmount; // Spread between price of left and right order, denominated in the left order's makerAsset, paid to taker.
|
||||
}
|
||||
|
||||
/// @dev Adds properties of both FillResults instances.
|
||||
/// Modifies the first FillResults instance specified.
|
||||
/// @param totalFillResults Fill results instance that will be added onto.
|
||||
/// @param singleFillResults Fill results instance that will be added to totalFillResults.
|
||||
function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount);
|
||||
totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount);
|
||||
totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid);
|
||||
totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid);
|
||||
}
|
||||
}
|
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
|
||||
|
||||
|
||||
contract LibMath is
|
||||
SafeMath
|
||||
{
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded down.
|
||||
function safeGetPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
require(
|
||||
!isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
),
|
||||
"ROUNDING_ERROR"
|
||||
);
|
||||
|
||||
partialAmount = safeDiv(
|
||||
safeMul(numerator, target),
|
||||
denominator
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded up.
|
||||
function safeGetPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
require(
|
||||
!isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
),
|
||||
"ROUNDING_ERROR"
|
||||
);
|
||||
|
||||
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||
// ceil(a / b) = floor((a + b - 1) / b)
|
||||
// To implement `ceil(a / b)` using safeDiv.
|
||||
partialAmount = safeDiv(
|
||||
safeAdd(
|
||||
safeMul(numerator, target),
|
||||
safeSub(denominator, 1)
|
||||
),
|
||||
denominator
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded down.
|
||||
function getPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
partialAmount = safeDiv(
|
||||
safeMul(numerator, target),
|
||||
denominator
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded up.
|
||||
function getPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||
// ceil(a / b) = floor((a + b - 1) / b)
|
||||
// To implement `ceil(a / b)` using safeDiv.
|
||||
partialAmount = safeDiv(
|
||||
safeAdd(
|
||||
safeMul(numerator, target),
|
||||
safeSub(denominator, 1)
|
||||
),
|
||||
denominator
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1% when rounding down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
// The absolute rounding error is the difference between the rounded
|
||||
// value and the ideal value. The relative rounding error is the
|
||||
// absolute rounding error divided by the absolute value of the
|
||||
// ideal value. This is undefined when the ideal value is zero.
|
||||
//
|
||||
// The ideal value is `numerator * target / denominator`.
|
||||
// Let's call `numerator * target % denominator` the remainder.
|
||||
// The absolute error is `remainder / denominator`.
|
||||
//
|
||||
// When the ideal value is zero, we require the absolute error to
|
||||
// be zero. Fortunately, this is always the case. The ideal value is
|
||||
// zero iff `numerator == 0` and/or `target == 0`. In this case the
|
||||
// remainder and absolute error are also zero.
|
||||
if (target == 0 || numerator == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we want the relative rounding error to be strictly
|
||||
// less than 0.1%.
|
||||
// The relative error is `remainder / (numerator * target)`.
|
||||
// We want the relative error less than 1 / 1000:
|
||||
// remainder / (numerator * denominator) < 1 / 1000
|
||||
// or equivalently:
|
||||
// 1000 * remainder < numerator * target
|
||||
// so we have a rounding error iff:
|
||||
// 1000 * remainder >= numerator * target
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
isError = safeMul(1000, remainder) >= safeMul(numerator, target);
|
||||
return isError;
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1% when rounding up.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
require(
|
||||
denominator > 0,
|
||||
"DIVISION_BY_ZERO"
|
||||
);
|
||||
|
||||
// See the comments in `isRoundingError`.
|
||||
if (target == 0 || numerator == 0) {
|
||||
// When either is zero, the ideal value and rounded value are zero
|
||||
// and there is no rounding error. (Although the relative error
|
||||
// is undefined.)
|
||||
return false;
|
||||
}
|
||||
// Compute remainder as before
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
remainder = safeSub(denominator, remainder) % denominator;
|
||||
isError = safeMul(1000, remainder) >= safeMul(numerator, target);
|
||||
return isError;
|
||||
}
|
||||
}
|
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "./LibEIP712.sol";
|
||||
|
||||
|
||||
contract LibOrder is
|
||||
LibEIP712
|
||||
{
|
||||
// Hash for the EIP712 Order Schema
|
||||
bytes32 constant internal EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked(
|
||||
"Order(",
|
||||
"address makerAddress,",
|
||||
"address takerAddress,",
|
||||
"address feeRecipientAddress,",
|
||||
"address senderAddress,",
|
||||
"uint256 makerAssetAmount,",
|
||||
"uint256 takerAssetAmount,",
|
||||
"uint256 makerFee,",
|
||||
"uint256 takerFee,",
|
||||
"uint256 expirationTimeSeconds,",
|
||||
"uint256 salt,",
|
||||
"bytes makerAssetData,",
|
||||
"bytes takerAssetData",
|
||||
")"
|
||||
));
|
||||
|
||||
// A valid order remains fillable until it is expired, fully filled, or cancelled.
|
||||
// An order's state is unaffected by external factors, like account balances.
|
||||
enum OrderStatus {
|
||||
INVALID, // Default value
|
||||
INVALID_MAKER_ASSET_AMOUNT, // Order does not have a valid maker asset amount
|
||||
INVALID_TAKER_ASSET_AMOUNT, // Order does not have a valid taker asset amount
|
||||
FILLABLE, // Order is fillable
|
||||
EXPIRED, // Order has already expired
|
||||
FULLY_FILLED, // Order is fully filled
|
||||
CANCELLED // Order has been cancelled
|
||||
}
|
||||
|
||||
// solhint-disable max-line-length
|
||||
struct Order {
|
||||
address makerAddress; // Address that created the order.
|
||||
address takerAddress; // Address that is allowed to fill the order. If set to 0, any address is allowed to fill the order.
|
||||
address feeRecipientAddress; // Address that will recieve fees when order is filled.
|
||||
address senderAddress; // Address that is allowed to call Exchange contract methods that affect this order. If set to 0, any address is allowed to call these methods.
|
||||
uint256 makerAssetAmount; // Amount of makerAsset being offered by maker. Must be greater than 0.
|
||||
uint256 takerAssetAmount; // Amount of takerAsset being bid on by maker. Must be greater than 0.
|
||||
uint256 makerFee; // Amount of ZRX paid to feeRecipient by maker when order is filled. If set to 0, no transfer of ZRX from maker to feeRecipient will be attempted.
|
||||
uint256 takerFee; // Amount of ZRX paid to feeRecipient by taker when order is filled. If set to 0, no transfer of ZRX from taker to feeRecipient will be attempted.
|
||||
uint256 expirationTimeSeconds; // Timestamp in seconds at which order expires.
|
||||
uint256 salt; // Arbitrary number to facilitate uniqueness of the order's hash.
|
||||
bytes makerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring makerAsset. The last byte references the id of this proxy.
|
||||
bytes takerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring takerAsset. The last byte references the id of this proxy.
|
||||
}
|
||||
// solhint-enable max-line-length
|
||||
|
||||
struct OrderInfo {
|
||||
uint8 orderStatus; // Status that describes order's validity and fillability.
|
||||
bytes32 orderHash; // EIP712 hash of the order (see LibOrder.getOrderHash).
|
||||
uint256 orderTakerAssetFilledAmount; // Amount of order that has already been filled.
|
||||
}
|
||||
|
||||
/// @dev Calculates Keccak-256 hash of the order.
|
||||
/// @param order The order structure.
|
||||
/// @return Keccak-256 EIP712 hash of the order.
|
||||
function getOrderHash(Order memory order)
|
||||
internal
|
||||
view
|
||||
returns (bytes32 orderHash)
|
||||
{
|
||||
orderHash = hashEIP712Message(hashOrder(order));
|
||||
return orderHash;
|
||||
}
|
||||
|
||||
/// @dev Calculates EIP712 hash of the order.
|
||||
/// @param order The order structure.
|
||||
/// @return EIP712 hash of the order.
|
||||
function hashOrder(Order memory order)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH;
|
||||
bytes32 makerAssetDataHash = keccak256(order.makerAssetData);
|
||||
bytes32 takerAssetDataHash = keccak256(order.takerAssetData);
|
||||
|
||||
// Assembly for more efficiently computing:
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP712_ORDER_SCHEMA_HASH,
|
||||
// bytes32(order.makerAddress),
|
||||
// bytes32(order.takerAddress),
|
||||
// bytes32(order.feeRecipientAddress),
|
||||
// bytes32(order.senderAddress),
|
||||
// order.makerAssetAmount,
|
||||
// order.takerAssetAmount,
|
||||
// order.makerFee,
|
||||
// order.takerFee,
|
||||
// order.expirationTimeSeconds,
|
||||
// order.salt,
|
||||
// keccak256(order.makerAssetData),
|
||||
// keccak256(order.takerAssetData)
|
||||
// ));
|
||||
|
||||
assembly {
|
||||
// Calculate memory addresses that will be swapped out before hashing
|
||||
let pos1 := sub(order, 32)
|
||||
let pos2 := add(order, 320)
|
||||
let pos3 := add(order, 352)
|
||||
|
||||
// Backup
|
||||
let temp1 := mload(pos1)
|
||||
let temp2 := mload(pos2)
|
||||
let temp3 := mload(pos3)
|
||||
|
||||
// Hash in place
|
||||
mstore(pos1, schemaHash)
|
||||
mstore(pos2, makerAssetDataHash)
|
||||
mstore(pos3, takerAssetDataHash)
|
||||
result := keccak256(pos1, 416)
|
||||
|
||||
// Restore
|
||||
mstore(pos1, temp1)
|
||||
mstore(pos2, temp2)
|
||||
mstore(pos3, temp3)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../libs/LibMath.sol";
|
||||
import "../../libs/LibOrder.sol";
|
||||
import "../../libs/LibFillResults.sol";
|
||||
import "../../libs/LibAbiEncoder.sol";
|
||||
|
||||
|
||||
contract TestLibs is
|
||||
LibMath,
|
||||
LibOrder,
|
||||
LibFillResults,
|
||||
LibAbiEncoder
|
||||
{
|
||||
function publicAbiEncodeFillOrder(
|
||||
Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory fillOrderCalldata)
|
||||
{
|
||||
fillOrderCalldata = abiEncodeFillOrder(
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
signature
|
||||
);
|
||||
return fillOrderCalldata;
|
||||
}
|
||||
|
||||
function publicGetPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
partialAmount = getPartialAmountFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
function publicGetPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
partialAmount = getPartialAmountCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
function publicIsRoundingErrorFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
isError = isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
return isError;
|
||||
}
|
||||
|
||||
function publicIsRoundingErrorCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
isError = isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
return isError;
|
||||
}
|
||||
|
||||
function publicGetOrderHash(Order memory order)
|
||||
public
|
||||
view
|
||||
returns (bytes32 orderHash)
|
||||
{
|
||||
orderHash = getOrderHash(order);
|
||||
return orderHash;
|
||||
}
|
||||
|
||||
function getOrderSchemaHash()
|
||||
public
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
return EIP712_ORDER_SCHEMA_HASH;
|
||||
}
|
||||
|
||||
function getDomainSeparatorSchemaHash()
|
||||
public
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
return EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;
|
||||
}
|
||||
|
||||
function publicAddFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)
|
||||
public
|
||||
pure
|
||||
returns (FillResults memory)
|
||||
{
|
||||
addFillResults(totalFillResults, singleFillResults);
|
||||
return totalFillResults;
|
||||
}
|
||||
}
|
@@ -1,91 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0x/contracts-libs",
|
||||
"version": "1.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Smart contract libs of 0x protocol",
|
||||
"main": "lib/src/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"test": "yarn run_mocha",
|
||||
"rebuild_and_test": "run-s build test",
|
||||
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
|
||||
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||
"compile": "sol-compiler --contracts-dir contracts",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||
"coverage:report:lcov": "istanbul report lcov",
|
||||
"test:circleci": "yarn test",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "generated-artifacts/@(LibMath|LibOrder|LibFillResults|LibAbiEncoder|TestLibs|LibEIP712).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/libs/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.19",
|
||||
"@0x/contracts-test-utils": "^1.0.2",
|
||||
"@0x/dev-utils": "^1.0.21",
|
||||
"@0x/sol-compiler": "^1.1.16",
|
||||
"@0x/sol-cov": "^2.1.16",
|
||||
"@0x/subproviders": "^2.1.8",
|
||||
"@0x/tslint-config": "^2.0.0",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.10",
|
||||
"@0x/contracts-multisig": "^1.0.1",
|
||||
"@0x/contracts-utils": "^1.0.1",
|
||||
"@0x/order-utils": "^3.0.7",
|
||||
"@0x/types": "^1.4.1",
|
||||
"@0x/typescript-typings": "^3.0.6",
|
||||
"@0x/utils": "^2.0.8",
|
||||
"@0x/web3-wrapper": "^3.2.1",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^1.1.4",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as LibAbiEncoder from '../../generated-artifacts/LibAbiEncoder.json';
|
||||
import * as LibEIP721 from '../../generated-artifacts/LibEIP712.json';
|
||||
import * as LibFillResults from '../../generated-artifacts/LibFillResults.json';
|
||||
import * as LibMath from '../../generated-artifacts/LibMath.json';
|
||||
import * as LibOrder from '../../generated-artifacts/LibOrder.json';
|
||||
import * as TestLibs from '../../generated-artifacts/TestLibs.json';
|
||||
|
||||
export const artifacts = {
|
||||
TestLibs: TestLibs as ContractArtifact,
|
||||
LibAbiEncoder: LibAbiEncoder as ContractArtifact,
|
||||
LibFillResults: LibFillResults as ContractArtifact,
|
||||
LibMath: LibMath as ContractArtifact,
|
||||
LibOrder: LibOrder as ContractArtifact,
|
||||
LibEIP721: LibEIP721 as ContractArtifact,
|
||||
};
|
@@ -1,2 +0,0 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
@@ -1,6 +0,0 @@
|
||||
export * from '../../generated-wrappers/test_libs';
|
||||
export * from '../../generated-wrappers/lib_abi_encoder';
|
||||
export * from '../../generated-wrappers/lib_fill_results';
|
||||
export * from '../../generated-wrappers/lib_math';
|
||||
export * from '../../generated-wrappers/lib_order';
|
||||
export * from '../../generated-wrappers/lib_e_i_p712';
|
@@ -1,125 +0,0 @@
|
||||
import {
|
||||
addressUtils,
|
||||
chaiSetup,
|
||||
constants,
|
||||
OrderFactory,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { TestLibsContract } from '../../generated-wrappers/test_libs';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('Exchange libs', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
let orderFactory: OrderFactory;
|
||||
let libs: TestLibsContract;
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const makerAddress = accounts[0];
|
||||
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
|
||||
|
||||
const defaultOrderParams = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
exchangeAddress: libs.address,
|
||||
makerAddress,
|
||||
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
|
||||
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
|
||||
takerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
|
||||
};
|
||||
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
// Note(albrow): These tests are designed to be supplemental to the
|
||||
// combinatorial tests in test/exchange/internal. They test specific edge
|
||||
// cases that are not covered by the combinatorial tests.
|
||||
describe('LibMath', () => {
|
||||
describe('isRoundingError', () => {
|
||||
it('should return true if there is a rounding error of 0.1%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(999);
|
||||
const target = new BigNumber(50);
|
||||
// rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.true();
|
||||
});
|
||||
it('should return false if there is a rounding of 0.09%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(9991);
|
||||
const target = new BigNumber(500);
|
||||
// rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.false();
|
||||
});
|
||||
it('should return true if there is a rounding error of 0.11%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(9989);
|
||||
const target = new BigNumber(500);
|
||||
// rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('isRoundingErrorCeil', () => {
|
||||
it('should return true if there is a rounding error of 0.1%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(1001);
|
||||
const target = new BigNumber(50);
|
||||
// rounding error = (ceil(20*50/1001) - (20*50/1001)) / (20*50/1001) = 0.1%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.true();
|
||||
});
|
||||
it('should return false if there is a rounding of 0.09%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(10009);
|
||||
const target = new BigNumber(500);
|
||||
// rounding error = (ceil(20*500/10009) - (20*500/10009)) / (20*500/10009) = 0.09%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.false();
|
||||
});
|
||||
it('should return true if there is a rounding error of 0.11%', async () => {
|
||||
const numerator = new BigNumber(20);
|
||||
const denominator = new BigNumber(10011);
|
||||
const target = new BigNumber(500);
|
||||
// rounding error = (ceil(20*500/10011) - (20*500/10011)) / (20*500/10011) = 0.11%
|
||||
const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(isRoundingError).to.be.true();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('LibOrder', () => {
|
||||
describe('getOrderHash', () => {
|
||||
it('should output the correct orderHash', async () => {
|
||||
signedOrder = await orderFactory.newSignedOrderAsync();
|
||||
const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
|
||||
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,17 +0,0 @@
|
||||
import { env, EnvVars } from '@0x/dev-utils';
|
||||
|
||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||
before('start web3 provider', () => {
|
||||
provider.start();
|
||||
});
|
||||
after('generate coverage report', async () => {
|
||||
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
|
||||
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
|
||||
await coverageSubprovider.writeCoverageAsync();
|
||||
}
|
||||
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
|
||||
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
|
||||
await profilerSubprovider.writeProfilerOutputAsync();
|
||||
}
|
||||
provider.stop();
|
||||
});
|
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"./generated-artifacts/TestLibs.json",
|
||||
"./generated-artifacts/LibOrder.json",
|
||||
"./generated-artifacts/LibFillResults.json",
|
||||
"./generated-artifacts/LibAbiEncoder.json",
|
||||
"./generated-artifacts/LibEIP712.json",
|
||||
"./generated-artifacts/LibMath.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
[]
|
@@ -1,70 +0,0 @@
|
||||
## MultisSig Contracts
|
||||
|
||||
MultiSig smart contracts
|
||||
|
||||
## Usage
|
||||
|
||||
Contracts can be found in the [contracts](./contracts) directory. The contents of this directory are broken down into the following subdirectories:
|
||||
|
||||
* [multisig](./contracts/multisig)
|
||||
* This directory contains the [Gnosis MultiSigWallet](https://github.com/gnosis/MultiSigWallet) and a custom extension that adds a timelock to transactions within the MultiSigWallet.
|
||||
* [test](./contracts/test)
|
||||
* This directory contains mocks and other contracts that are used solely for testing contracts within the other directories.
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
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/contracts-multisig yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-multisig yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"compilerSettings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": ["MultiSigWallet", "MultiSigWalletWithTimeLock", "TestRejectEther"]
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract TestRejectEther {}
|
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0x/contracts-multisig",
|
||||
"version": "1.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Multisig contracts used by 0x protocol",
|
||||
"main": "lib/src/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"test": "yarn run_mocha",
|
||||
"rebuild_and_test": "run-s build test",
|
||||
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
|
||||
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||
"compile": "sol-compiler --contracts-dir contracts",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../packages/abi-gen-templates/contract.handlebars --partials '../../packages/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||
"coverage:report:lcov": "istanbul report lcov",
|
||||
"test:circleci": "yarn test",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "generated-artifacts/@(MultiSigWallet|MultiSigWalletWithTimeLock|TestRejectEther).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/multisig/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.19",
|
||||
"@0x/contracts-test-utils": "^1.0.2",
|
||||
"@0x/dev-utils": "^1.0.21",
|
||||
"@0x/sol-compiler": "^1.1.16",
|
||||
"@0x/sol-cov": "^2.1.16",
|
||||
"@0x/subproviders": "^2.1.8",
|
||||
"@0x/tslint-config": "^2.0.0",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/ethereumjs-abi": "^0.6.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.10",
|
||||
"@0x/order-utils": "^3.0.7",
|
||||
"@0x/types": "^1.4.1",
|
||||
"@0x/typescript-typings": "^3.0.6",
|
||||
"@0x/utils": "^2.0.8",
|
||||
"@0x/web3-wrapper": "^3.2.1",
|
||||
"ethereum-types": "^1.1.4",
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
|
||||
import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
|
||||
import * as TestRejectEther from '../../generated-artifacts/TestRejectEther.json';
|
||||
|
||||
export const artifacts = {
|
||||
TestRejectEther: TestRejectEther as ContractArtifact,
|
||||
MultiSigWallet: MultiSigWallet as ContractArtifact,
|
||||
MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
|
||||
};
|
@@ -1,2 +0,0 @@
|
||||
export * from '../../generated-wrappers/multi_sig_wallet';
|
||||
export * from '../../generated-wrappers/multi_sig_wallet_with_time_lock';
|
@@ -1,19 +0,0 @@
|
||||
import { env, EnvVars } from '@0x/dev-utils';
|
||||
|
||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||
|
||||
before('start web3 provider engine', () => {
|
||||
provider.start();
|
||||
});
|
||||
|
||||
after('generate coverage report', async () => {
|
||||
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
|
||||
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
|
||||
await coverageSubprovider.writeCoverageAsync();
|
||||
}
|
||||
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
|
||||
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
|
||||
await profilerSubprovider.writeProfilerOutputAsync();
|
||||
}
|
||||
provider.stop();
|
||||
});
|
@@ -1,349 +0,0 @@
|
||||
import {
|
||||
chaiSetup,
|
||||
constants,
|
||||
expectTransactionFailedAsync,
|
||||
expectTransactionFailedWithoutReasonAsync,
|
||||
increaseTimeAndMineBlockAsync,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { RevertReason } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
MultiSigWalletWithTimeLockConfirmationEventArgs,
|
||||
MultiSigWalletWithTimeLockConfirmationTimeSetEventArgs,
|
||||
MultiSigWalletWithTimeLockContract,
|
||||
MultiSigWalletWithTimeLockExecutionEventArgs,
|
||||
MultiSigWalletWithTimeLockExecutionFailureEventArgs,
|
||||
MultiSigWalletWithTimeLockSubmissionEventArgs,
|
||||
} from '../generated-wrappers/multi_sig_wallet_with_time_lock';
|
||||
import { TestRejectEtherContract } from '../generated-wrappers/test_reject_ether';
|
||||
import { artifacts } from '../src/artifacts';
|
||||
|
||||
import { MultiSigWrapper } from './utils/multi_sig_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
describe('MultiSigWalletWithTimeLock', () => {
|
||||
let owners: string[];
|
||||
let notOwner: string;
|
||||
const REQUIRED_APPROVALS = new BigNumber(2);
|
||||
const SECONDS_TIME_LOCKED = new BigNumber(1000000);
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
owners = [accounts[0], accounts[1], accounts[2]];
|
||||
notOwner = accounts[3];
|
||||
});
|
||||
|
||||
let multiSig: MultiSigWalletWithTimeLockContract;
|
||||
let multiSigWrapper: MultiSigWrapper;
|
||||
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
describe('external_call', () => {
|
||||
it('should be internal', async () => {
|
||||
const secondsTimeLocked = new BigNumber(0);
|
||||
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiSigWalletWithTimeLock,
|
||||
provider,
|
||||
txDefaults,
|
||||
owners,
|
||||
REQUIRED_APPROVALS,
|
||||
secondsTimeLocked,
|
||||
);
|
||||
expect(_.isUndefined((multiSig as any).external_call)).to.be.equal(true);
|
||||
});
|
||||
});
|
||||
describe('confirmTransaction', () => {
|
||||
let txId: BigNumber;
|
||||
beforeEach(async () => {
|
||||
const secondsTimeLocked = new BigNumber(0);
|
||||
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiSigWalletWithTimeLock,
|
||||
provider,
|
||||
txDefaults,
|
||||
owners,
|
||||
REQUIRED_APPROVALS,
|
||||
secondsTimeLocked,
|
||||
);
|
||||
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
||||
const destination = notOwner;
|
||||
const data = constants.NULL_BYTES;
|
||||
const txReceipt = await multiSigWrapper.submitTransactionAsync(destination, data, owners[0]);
|
||||
txId = (txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>).args
|
||||
.transactionId;
|
||||
});
|
||||
it('should revert if called by a non-owner', async () => {
|
||||
await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.confirmTransactionAsync(txId, notOwner));
|
||||
});
|
||||
it('should revert if transaction does not exist', async () => {
|
||||
const nonexistentTxId = new BigNumber(123456789);
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
multiSigWrapper.confirmTransactionAsync(nonexistentTxId, owners[1]),
|
||||
);
|
||||
});
|
||||
it('should revert if transaction is already confirmed by caller', async () => {
|
||||
await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.confirmTransactionAsync(txId, owners[0]));
|
||||
});
|
||||
it('should confirm transaction for caller and log a Confirmation event', async () => {
|
||||
const txReceipt = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockConfirmationEventArgs>;
|
||||
expect(log.event).to.be.equal('Confirmation');
|
||||
expect(log.args.sender).to.be.equal(owners[1]);
|
||||
expect(log.args.transactionId).to.be.bignumber.equal(txId);
|
||||
});
|
||||
it('should revert if fully confirmed', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await expectTransactionFailedAsync(
|
||||
multiSigWrapper.confirmTransactionAsync(txId, owners[2]),
|
||||
RevertReason.TxFullyConfirmed,
|
||||
);
|
||||
});
|
||||
it('should set the confirmation time of the transaction if it becomes fully confirmed', async () => {
|
||||
const txReceipt = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
||||
const timestamp = new BigNumber(await web3Wrapper.getBlockTimestampAsync(blockNum));
|
||||
const log = txReceipt.logs[1] as LogWithDecodedArgs<MultiSigWalletWithTimeLockConfirmationTimeSetEventArgs>;
|
||||
expect(log.args.confirmationTime).to.be.bignumber.equal(timestamp);
|
||||
expect(log.args.transactionId).to.be.bignumber.equal(txId);
|
||||
});
|
||||
});
|
||||
describe('executeTransaction', () => {
|
||||
let txId: BigNumber;
|
||||
const secondsTimeLocked = new BigNumber(1000000);
|
||||
beforeEach(async () => {
|
||||
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiSigWalletWithTimeLock,
|
||||
provider,
|
||||
txDefaults,
|
||||
owners,
|
||||
REQUIRED_APPROVALS,
|
||||
secondsTimeLocked,
|
||||
);
|
||||
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
||||
const destination = notOwner;
|
||||
const data = constants.NULL_BYTES;
|
||||
const txReceipt = await multiSigWrapper.submitTransactionAsync(destination, data, owners[0]);
|
||||
txId = (txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>).args
|
||||
.transactionId;
|
||||
});
|
||||
it('should revert if transaction has not been fully confirmed', async () => {
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
await expectTransactionFailedAsync(
|
||||
multiSigWrapper.executeTransactionAsync(txId, owners[1]),
|
||||
RevertReason.TxNotFullyConfirmed,
|
||||
);
|
||||
});
|
||||
it('should revert if time lock has not passed', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await expectTransactionFailedAsync(
|
||||
multiSigWrapper.executeTransactionAsync(txId, owners[1]),
|
||||
RevertReason.TimeLockIncomplete,
|
||||
);
|
||||
});
|
||||
it('should execute a transaction and log an Execution event if successful and called by owner', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, owners[1]);
|
||||
const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>;
|
||||
expect(log.event).to.be.equal('Execution');
|
||||
expect(log.args.transactionId).to.be.bignumber.equal(txId);
|
||||
});
|
||||
it('should execute a transaction and log an Execution event if successful and called by non-owner', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, notOwner);
|
||||
const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>;
|
||||
expect(log.event).to.be.equal('Execution');
|
||||
expect(log.args.transactionId).to.be.bignumber.equal(txId);
|
||||
});
|
||||
it('should revert if a required confirmation is revoked before executeTransaction is called', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
await multiSigWrapper.revokeConfirmationAsync(txId, owners[0]);
|
||||
await expectTransactionFailedAsync(
|
||||
multiSigWrapper.executeTransactionAsync(txId, owners[1]),
|
||||
RevertReason.TxNotFullyConfirmed,
|
||||
);
|
||||
});
|
||||
it('should revert if transaction has been executed', async () => {
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, owners[1]);
|
||||
const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>;
|
||||
expect(log.args.transactionId).to.be.bignumber.equal(txId);
|
||||
await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.executeTransactionAsync(txId, owners[1]));
|
||||
});
|
||||
it("should log an ExecutionFailure event and not update the transaction's execution state if unsuccessful", async () => {
|
||||
const contractWithoutFallback = await TestRejectEtherContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestRejectEther,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
const data = constants.NULL_BYTES;
|
||||
const value = new BigNumber(10);
|
||||
const submissionTxReceipt = await multiSigWrapper.submitTransactionAsync(
|
||||
contractWithoutFallback.address,
|
||||
data,
|
||||
owners[0],
|
||||
{ value },
|
||||
);
|
||||
const newTxId = (submissionTxReceipt.logs[0] as LogWithDecodedArgs<
|
||||
MultiSigWalletWithTimeLockSubmissionEventArgs
|
||||
>).args.transactionId;
|
||||
await multiSigWrapper.confirmTransactionAsync(newTxId, owners[1]);
|
||||
await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber());
|
||||
const txReceipt = await multiSigWrapper.executeTransactionAsync(newTxId, owners[1]);
|
||||
const executionFailureLog = txReceipt.logs[0] as LogWithDecodedArgs<
|
||||
MultiSigWalletWithTimeLockExecutionFailureEventArgs
|
||||
>;
|
||||
expect(executionFailureLog.event).to.be.equal('ExecutionFailure');
|
||||
expect(executionFailureLog.args.transactionId).to.be.bignumber.equal(newTxId);
|
||||
});
|
||||
});
|
||||
describe('changeTimeLock', () => {
|
||||
describe('initially non-time-locked', async () => {
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
before('deploy a wallet', async () => {
|
||||
const secondsTimeLocked = new BigNumber(0);
|
||||
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiSigWalletWithTimeLock,
|
||||
provider,
|
||||
txDefaults,
|
||||
owners,
|
||||
REQUIRED_APPROVALS,
|
||||
secondsTimeLocked,
|
||||
);
|
||||
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
||||
});
|
||||
|
||||
it('should throw when not called by wallet', async () => {
|
||||
return expectTransactionFailedWithoutReasonAsync(
|
||||
multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw without enough confirmations', async () => {
|
||||
const destination = multiSig.address;
|
||||
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED);
|
||||
const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
|
||||
const log = res.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>;
|
||||
const txId = log.args.transactionId;
|
||||
return expectTransactionFailedAsync(
|
||||
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||
RevertReason.TxNotFullyConfirmed,
|
||||
);
|
||||
});
|
||||
|
||||
it('should set confirmation time with enough confirmations', async () => {
|
||||
const destination = multiSig.address;
|
||||
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED);
|
||||
const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
|
||||
const subLog = subRes.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>;
|
||||
const txId = subLog.args.transactionId;
|
||||
|
||||
const confirmRes = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
expect(confirmRes.logs).to.have.length(2);
|
||||
|
||||
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
||||
const blockInfo = await web3Wrapper.getBlockIfExistsAsync(blockNum);
|
||||
if (_.isUndefined(blockInfo)) {
|
||||
throw new Error(`Unexpectedly failed to fetch block at #${blockNum}`);
|
||||
}
|
||||
const timestamp = new BigNumber(blockInfo.timestamp);
|
||||
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.callAsync(txId));
|
||||
|
||||
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
|
||||
});
|
||||
|
||||
it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => {
|
||||
const destination = multiSig.address;
|
||||
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED);
|
||||
const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
|
||||
const subLog = subRes.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>;
|
||||
const txId = subLog.args.transactionId;
|
||||
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
await multiSigWrapper.executeTransactionAsync(txId, owners[1]);
|
||||
|
||||
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync());
|
||||
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
|
||||
});
|
||||
});
|
||||
describe('initially time-locked', async () => {
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
let txId: BigNumber;
|
||||
const newSecondsTimeLocked = new BigNumber(0);
|
||||
before('deploy a wallet, submit transaction to change timelock, and confirm the transaction', async () => {
|
||||
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiSigWalletWithTimeLock,
|
||||
provider,
|
||||
txDefaults,
|
||||
owners,
|
||||
REQUIRED_APPROVALS,
|
||||
SECONDS_TIME_LOCKED,
|
||||
);
|
||||
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
||||
|
||||
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(newSecondsTimeLocked);
|
||||
const res = await multiSigWrapper.submitTransactionAsync(
|
||||
multiSig.address,
|
||||
changeTimeLockData,
|
||||
owners[0],
|
||||
);
|
||||
const log = res.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>;
|
||||
txId = log.args.transactionId;
|
||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||
});
|
||||
|
||||
it('should throw if it has enough confirmations but is not past the time lock', async () => {
|
||||
return expectTransactionFailedAsync(
|
||||
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||
RevertReason.TimeLockIncomplete,
|
||||
);
|
||||
});
|
||||
|
||||
it('should execute if it has enough confirmations and is past the time lock', async () => {
|
||||
await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync());
|
||||
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:enable:no-unnecessary-type-assertion
|
@@ -1,54 +0,0 @@
|
||||
import { LogDecoder } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { MultiSigWalletContract } from '../../generated-wrappers/multi_sig_wallet';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
|
||||
export class MultiSigWrapper {
|
||||
private readonly _multiSig: MultiSigWalletContract;
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _logDecoder: LogDecoder;
|
||||
constructor(multiSigContract: MultiSigWalletContract, provider: Provider) {
|
||||
this._multiSig = multiSigContract;
|
||||
this._web3Wrapper = new Web3Wrapper(provider);
|
||||
this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
|
||||
}
|
||||
public async submitTransactionAsync(
|
||||
destination: string,
|
||||
data: string,
|
||||
from: string,
|
||||
opts: { value?: BigNumber } = {},
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const value = _.isUndefined(opts.value) ? new BigNumber(0) : opts.value;
|
||||
const txHash = await this._multiSig.submitTransaction.sendTransactionAsync(destination, value, data, {
|
||||
from,
|
||||
});
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async confirmTransactionAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._multiSig.confirmTransaction.sendTransactionAsync(txId, { from });
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async revokeConfirmationAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._multiSig.revokeConfirmation.sendTransactionAsync(txId, { from });
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
public async executeTransactionAsync(
|
||||
txId: BigNumber,
|
||||
from: string,
|
||||
opts: { gas?: number } = {},
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._multiSig.executeTransaction.sendTransactionAsync(txId, {
|
||||
from,
|
||||
gas: opts.gas,
|
||||
});
|
||||
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return tx;
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"./generated-artifacts/MultiSigWallet.json",
|
||||
"./generated-artifacts/MultiSigWalletWithTimeLock.json",
|
||||
"./generated-artifacts/TestRejectEther.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user